9 |
--------------------------------------------------------------------------------
/contao/dca/tl_layout.php:
--------------------------------------------------------------------------------
1 | 'checkbox',
9 | 'label' => &$GLOBALS['TL_LANG']['tl_layout']['cp_grid_load_css'],
10 | 'sql' => "char(1) NOT NULL default '1'",
11 | ];
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.{php,twig,yml}]
13 | indent_style = space
14 | indent_size = 4
15 |
16 | [*.{html5,svg,min.css,min.js}]
17 | insert_final_newline = false
18 |
--------------------------------------------------------------------------------
/contao/languages/de/tl_layout.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ./tests
15 |
16 |
17 |
18 |
19 |
20 | ./src
21 |
22 | ./src/Resources
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/tests/ContaoClickpressJsBundleTest.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf('Clickpress\ContaoClickpressGridBundle\ContaoClickpressGridBundle', $bundle);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ContaoClickpressGridBundle.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle;
17 |
18 | use Symfony\Component\DependencyInjection\ContainerBuilder;
19 | use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
20 | use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
21 |
22 | class ContaoClickpressGridBundle extends AbstractBundle
23 | {
24 | public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
25 | {
26 | $container->import('../config/services.yaml');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ContaoManager/Plugin.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\ContaoManager;
17 |
18 | use Clickpress\ContaoClickpressGridBundle\ContaoClickpressGridBundle;
19 | use Contao\CoreBundle\ContaoCoreBundle;
20 | use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
21 | use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
22 | use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
23 |
24 | class Plugin implements BundlePluginInterface
25 | {
26 | public function getBundles(ParserInterface $parser): array
27 | {
28 | return [
29 | BundleConfig::create(ContaoClickpressGridBundle::class)
30 | ->setLoadAfter([ContaoCoreBundle::class]),
31 | ];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/contao/languages/de/default.php:
--------------------------------------------------------------------------------
1 |
18 | * @author Stefan Schulz-Lauterbach
19 | * @author Jannik Nölke
20 | */
21 |
22 | use Clickpress\ContaoClickpressGridBundle\Forms\FormGridColumnStart;
23 | use Clickpress\ContaoClickpressGridBundle\Forms\FormGridColumnStop;
24 | use Clickpress\ContaoClickpressGridBundle\Forms\FormGridStart;
25 | use Clickpress\ContaoClickpressGridBundle\Forms\FormGridStop;
26 |
27 | $GLOBALS['TL_WRAPPERS']['start'][] = 'cp_grid_start';
28 | $GLOBALS['TL_WRAPPERS']['stop'][] = 'cp_grid_stop';
29 | $GLOBALS['TL_WRAPPERS']['start'][] = 'cp_column_start';
30 | $GLOBALS['TL_WRAPPERS']['stop'][] = 'cp_column_stop';
31 |
32 | $GLOBALS['TL_FFL']['cp_grid_start'] = FormGridStart::class;
33 | $GLOBALS['TL_FFL']['cp_grid_stop'] = FormGridStop::class;
34 | $GLOBALS['TL_FFL']['cp_column_start'] = FormGridColumnStart::class;
35 | $GLOBALS['TL_FFL']['cp_column_stop'] = FormGridColumnStop::class;
36 |
--------------------------------------------------------------------------------
/public/clickpress-grid.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["clickpress-grid.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;AAEA;EACE;;;AAIJ;EACE;;;AAGF;EACE;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;;AAIJ;EACE;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;;AAKJ;EACE;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAGF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE;;EAEF;IACE","file":"clickpress-grid.css"}
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "clickpress/contao-clickpress-grid",
3 | "type": "contao-bundle",
4 | "description": "Grid System for Contao based on CSS Grid",
5 | "license": "LGPL-3.0-or-later",
6 | "authors": [
7 | {
8 | "name": "Stefan Schulz-Lauterbach",
9 | "email": "ssl@clickpress.de",
10 | "homepage": "https://clickpress.de",
11 | "role": "Developer"
12 | },
13 | {
14 | "name": "Martin Auswöger",
15 | "email": "martin@madeyourday.net",
16 | "homepage": "https://madeyourday.net",
17 | "role": "Developer"
18 | },
19 | {
20 | "name": "Jannik Nölke",
21 | "email": "mail@jaynoe.de",
22 | "homepage": "https://plakart.net",
23 | "role": "Developer"
24 | }
25 | ],
26 | "require": {
27 | "php": "^8.1",
28 | "contao/core-bundle": "^5.3"
29 | },
30 | "conflict": {
31 | "contao/manager-plugin": "<2.0 || >=3.0"
32 | },
33 | "require-dev": {
34 | "contao/manager-plugin": "^2.3",
35 | "contao/easy-coding-standard": "^3.1",
36 | "phpunit/phpunit": "^9.3",
37 | "symfony/phpunit-bridge": "^5.4"
38 | },
39 | "extra": {
40 | "contao-manager-plugin": "Clickpress\\ContaoClickpressGridBundle\\ContaoManager\\Plugin"
41 | },
42 | "autoload": {
43 | "psr-4": {
44 | "Clickpress\\ContaoClickpressGridBundle\\": "src/"
45 | }
46 | },
47 | "autoload-dev": {
48 | "psr-4": {
49 | "Clickpress\\ContaoClickpressGridBundle\\Tests\\": "tests/"
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Forms/FormGridStop.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Forms;
17 |
18 | use Contao\BackendTemplate;
19 | use Contao\System;
20 | use Contao\Widget;
21 |
22 | /**
23 | * Grid stop content element Taken with friendly permission from RockSolid Columns.
24 | */
25 | class FormGridStop extends Widget
26 | {
27 | /**
28 | * @var string Template
29 | */
30 | protected $strTemplate = 'form_grid_stop';
31 |
32 | /**
33 | * Do not validate.
34 | */
35 | public function validate(): void
36 | {
37 | }
38 |
39 | /**
40 | * Parse the template file and return it as string.
41 | *
42 | * @param array $arrAttributes An optional attributes array
43 | *
44 | * @return string The template markup
45 | */
46 | public function parse($arrAttributes = null): string
47 | {
48 | $request = System::getContainer()->get('request_stack')->getCurrentRequest();
49 |
50 | if ($request && System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request)) {
51 | $objTemplate = new BackendTemplate('be_wildcard');
52 |
53 | return $objTemplate->parse();
54 | }
55 |
56 | return parent::parse($arrAttributes);
57 | }
58 |
59 | /**
60 | * Generate the widget and return it as string.
61 | *
62 | * @return string The widget markup
63 | */
64 | public function generate(): string
65 | {
66 | return '';
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Forms/FormGridColumnStop.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Forms;
17 |
18 | use Contao\BackendTemplate;
19 | use Contao\System;
20 | use Contao\Widget;
21 |
22 | /**
23 | * Column stop content element Taken with friendly permission from RockSolid Columns.
24 | */
25 | class FormGridColumnStop extends Widget
26 | {
27 | /**
28 | * @var string Template
29 | */
30 | protected $strTemplate = 'form_grid_column_stop';
31 |
32 | /**
33 | * Do not validate.
34 | */
35 | public function validate(): void
36 | {
37 | }
38 |
39 | /**
40 | * Parse the template file and return it as string.
41 | *
42 | * @param array $arrAttributes An optional attributes array
43 | *
44 | * @return string The template markup
45 | */
46 | public function parse($arrAttributes = null): string
47 | {
48 | $request = System::getContainer()->get('request_stack')->getCurrentRequest();
49 |
50 | if ($request && System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request)) {
51 | $objTemplate = new BackendTemplate('be_wildcard');
52 |
53 | return $objTemplate->parse();
54 | }
55 |
56 | return parent::parse($arrAttributes);
57 | }
58 |
59 | /**
60 | * Generate the widget and return it as string.
61 | *
62 | * @return string The widget markup
63 | */
64 | public function generate(): string
65 | {
66 | return '';
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Forms/FormGridColumnStart.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Forms;
17 |
18 | use Contao\BackendTemplate;
19 | use Contao\System;
20 | use Contao\Widget;
21 |
22 | /**
23 | * Column start content element Taken with friendly permission from RockSolid Columns.
24 | */
25 | class FormGridColumnStart extends Widget
26 | {
27 | /**
28 | * @var string Template
29 | */
30 | protected $strTemplate = 'form_grid_column_start';
31 |
32 | /**
33 | * Do not validate.
34 | */
35 | public function validate(): void
36 | {
37 | }
38 |
39 | /**
40 | * Parse the template file and return it as string.
41 | *
42 | * @param array $arrAttributes An optional attributes array
43 | *
44 | * @return string The template markup
45 | */
46 | public function parse($arrAttributes = null): string
47 | {
48 | $request = System::getContainer()->get('request_stack')->getCurrentRequest();
49 |
50 | if ($request && System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request)) {
51 | $objTemplate = new BackendTemplate('be_wildcard');
52 |
53 | return $objTemplate->parse();
54 | }
55 |
56 | return parent::parse($arrAttributes);
57 | }
58 |
59 | /**
60 | * Generate the widget and return it as string.
61 | *
62 | * @return string The widget markup
63 | */
64 | public function generate(): string
65 | {
66 | return '';
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Element/GridColumnStop.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Element;
17 |
18 | use Contao\ContentModel;
19 | use Contao\CoreBundle\Controller\ContentElement\AbstractContentElementController;
20 | use Contao\CoreBundle\DependencyInjection\Attribute\AsContentElement;
21 | use Contao\CoreBundle\Routing\ScopeMatcher;
22 | use Contao\Template;
23 | use Symfony\Component\HttpFoundation\Request;
24 | use Symfony\Component\HttpFoundation\RequestStack;
25 | use Symfony\Component\HttpFoundation\Response;
26 |
27 | /**
28 | * Column stop content element Taken with friendly permission from RockSolid Columns.
29 | */
30 | #[AsContentElement(type: 'cp_column_stop', category: 'cp_grid', template: 'ce_grid_column_stop')]
31 | class GridColumnStop extends AbstractContentElementController
32 | {
33 | public function __construct(readonly RequestStack $requestStack, readonly ScopeMatcher $scopeMatcher)
34 | {
35 | }
36 |
37 | protected function getResponse(Template $template, ContentModel $model, Request $request): Response
38 | {
39 | if ($this->scopeMatcher->isBackendRequest($this->requestStack->getCurrentRequest())) {
40 | return new Response('');
41 | }
42 |
43 | $parentKey = ($model->ptable ?: 'tl_article').'__'.$model->pid;
44 | if (isset($GLOBALS['TL_CP_GRID'][$parentKey]) && !$GLOBALS['TL_CP_GRID'][$parentKey]['active']) {
45 | $GLOBALS['TL_CP_GRID'][$parentKey]['active'] = true;
46 | }
47 |
48 | return $template->getResponse();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/contao/languages/en/tl_form_field.php:
--------------------------------------------------------------------------------
1 | '1 column',
12 | 'grid_50_50' => '2 columns',
13 | 'grid_33_33_33' => '3 columns',
14 | 'grid_25_25_25_25' => '4 columns',
15 | 'grid_75_25' => '2 columns - divided into 75% 25%',
16 | 'grid_25_75' => '2 columns - divided into 25% 75%',
17 | 'grid_66_33' => '2 columns - divided into 66% 33%',
18 | 'grid_33_66' => '2 columns - divided into 33% 66%',
19 | 'grid_60_40' => '2 columns - divided into 60% 40%',
20 | 'grid_40_60' => '2 columns - divided into 40% 60%',
21 | 'grid_50_25_25' => '3 columns - divided into 50% 25% 25%',
22 | 'grid_25_50_25' => '3 columns - divided into 25% 50% 25%',
23 | 'grid_25_25_50' => '3 columns - divided into 25% 25% 50%',
24 | 'grid_40_30_30' => '3 columns - divided into 40% 30% 30%',
25 | 'grid_30_40_30' => '3 columns - divided into 30% 40% 30%',
26 | 'grid_30_30_40' => '3 columns - divided into 30% 30% 40%',
27 | 'grid_20_40_40' => '3 columns - divided into 20% 40% 40%',
28 | 'grid_40_20_40' => '3 columns - divided into 40% 20% 40%',
29 | 'grid_40_40_20' => '3 columns - divided into 40% 40% 20%',
30 | 'grid_40_20_20_20' => '4 columns - divided into 40% 20% 20% 20%',
31 | 'grid_20_40_20_20' => '4 columns - divided into 20% 40% 20% 20%',
32 | 'grid_20_20_40_20' => '4 columns - divided into 20% 20% 40% 20%',
33 | 'grid_20_20_20_40' => '4 columns - divided into 20% 20% 20% 40%',
34 | ];
35 |
36 | // Legend
37 | $GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_legend'] = 'Column configuration';
38 |
--------------------------------------------------------------------------------
/src/Element/GridColumnStart.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Element;
17 |
18 | use Contao\ContentModel;
19 | use Contao\CoreBundle\Controller\ContentElement\AbstractContentElementController;
20 | use Contao\CoreBundle\DependencyInjection\Attribute\AsContentElement;
21 | use Contao\CoreBundle\Routing\ScopeMatcher;
22 | use Contao\StringUtil;
23 | use Contao\Template;
24 | use Symfony\Component\HttpFoundation\Request;
25 | use Symfony\Component\HttpFoundation\RequestStack;
26 | use Symfony\Component\HttpFoundation\Response;
27 |
28 | /**
29 | * Column start content element Taken with friendly permission from RockSolid Columns.
30 | */
31 | #[AsContentElement(type: 'cp_column_start', category: 'cp_grid', template: 'ce_grid_column_start')]
32 | class GridColumnStart extends AbstractContentElementController
33 | {
34 | public function __construct(readonly RequestStack $requestStack, readonly ScopeMatcher $scopeMatcher)
35 | {
36 | }
37 |
38 | protected function getResponse(Template $template, ContentModel $model, Request $request): Response
39 | {
40 | if ($this->scopeMatcher->isBackendRequest($this->requestStack->getCurrentRequest())) {
41 | $listingTitle = '';
42 |
43 | if($model->headline) {
44 | $headline = StringUtil::deserialize($model->headline, true);
45 | $listingTitle = $headline['value'];
46 | }
47 |
48 | if($model->title) {
49 | $listingTitle = $model->title;
50 | }
51 |
52 | return new Response($listingTitle);
53 | }
54 |
55 | return $template->getResponse();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/contao/languages/de/tl_form_field.php:
--------------------------------------------------------------------------------
1 | '1 Spalte',
12 | 'grid_50_50' => '2 Spalten',
13 | 'grid_33_33_33' => '3 Spalten',
14 | 'grid_25_25_25_25' => '4 Spalten',
15 | 'grid_20_20_20_20_20' => '5 Spalten',
16 | 'grid_75_25' => '2 Spalten - aufgeteilt in 75% 25%',
17 | 'grid_25_75' => '2 Spalten - aufgeteilt in 25% 75%',
18 | 'grid_66_33' => '2 Spalten - aufgeteilt in 66% 33%',
19 | 'grid_33_66' => '2 Spalten - aufgeteilt in 33% 66%',
20 | 'grid_60_40' => '2 Spalten - aufgeteilt in 60% 40%',
21 | 'grid_40_60' => '2 Spalten - aufgeteilt in 40% 60%',
22 | 'grid_50_25_25' => '3 Spalten - aufgeteilt in 50% 25% 25%',
23 | 'grid_25_50_25' => '3 Spalten - aufgeteilt in 25% 50% 25%',
24 | 'grid_25_25_50' => '3 Spalten - aufgeteilt in 25% 25% 50%',
25 | 'grid_40_30_30' => '3 Spalten - aufgeteilt in 40% 30% 30%',
26 | 'grid_30_40_30' => '3 Spalten - aufgeteilt in 30% 40% 30%',
27 | 'grid_30_30_40' => '3 Spalten - aufgeteilt in 30% 30% 40%',
28 | 'grid_20_40_40' => '3 Spalten - aufgeteilt in 20% 40% 40%',
29 | 'grid_40_20_40' => '3 Spalten - aufgeteilt in 40% 20% 40%',
30 | 'grid_40_40_20' => '3 Spalten - aufgeteilt in 40% 40% 20%',
31 | 'grid_40_20_20_20' => '4 Spalten - aufgeteilt in 40% 20% 20% 20%',
32 | 'grid_20_40_20_20' => '4 Spalten - aufgeteilt in 20% 40% 20% 20%',
33 | 'grid_20_20_40_20' => '4 Spalten - aufgeteilt in 20% 20% 40% 20%',
34 | 'grid_20_20_20_40' => '4 Spalten - aufgeteilt in 20% 20% 20% 40%',
35 | ];
36 |
37 | // Legend
38 | $GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_legend'] = 'Spalten-Konfiguration';
39 |
--------------------------------------------------------------------------------
/.php_cs.dist:
--------------------------------------------------------------------------------
1 | exclude('Resources')
14 | ->in([__DIR__.'/src', __DIR__.'/tests'])
15 | ;
16 |
17 | return PhpCsFixer\Config::create()
18 | ->setRules([
19 | '@Symfony' => true,
20 | '@Symfony:risky' => true,
21 | '@PHPUnit60Migration:risky' => true,
22 | 'align_multiline_comment' => true,
23 | 'array_syntax' => ['syntax' => 'short'],
24 | 'combine_consecutive_issets' => true,
25 | 'combine_consecutive_unsets' => true,
26 | 'compact_nullable_typehint' => true,
27 | 'concat_space' => ['spacing' => 'one'],
28 | 'general_phpdoc_annotation_remove' => [
29 | 'expectedException',
30 | 'expectedExceptionMessage',
31 | ],
32 | 'header_comment' => ['header' => $header],
33 | 'heredoc_to_nowdoc' => true,
34 | 'linebreak_after_opening_tag' => true,
35 | 'native_function_invocation' => [
36 | 'include' => ['@compiler_optimized'],
37 | ],
38 | 'no_null_property_initialization' => true,
39 | 'no_superfluous_elseif' => true,
40 | 'no_unreachable_default_argument_value' => true,
41 | 'no_useless_else' => true,
42 | 'no_useless_return' => true,
43 | 'ordered_class_elements' => true,
44 | 'ordered_imports' => true,
45 | 'php_unit_strict' => true,
46 | 'phpdoc_add_missing_param_annotation' => true,
47 | 'phpdoc_order' => true,
48 | 'phpdoc_types_order' => [
49 | 'null_adjustment' => 'always_last',
50 | 'sort_algorithm' => 'none',
51 | ],
52 | 'strict_comparison' => true,
53 | 'strict_param' => true,
54 | ])
55 | ->setFinder($finder)
56 | ->setRiskyAllowed(true)
57 | ->setUsingCache(false)
58 | ;
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://packagist.org/packages/clickpress/contao-clickpress-grid) [](https://raw.githubusercontent.com/clickpress/contao-clickpress-grid/master/LICENSE)
2 | # Grid CSS for Contao
3 |
4 | Add columns to your page content.
5 |
6 | Contao Clickpress Grid uses [CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) and so less HTML is needed.
7 |
8 | ## Installation
9 | ```console
10 | composer require clickpress/contao-clickpress-grid
11 | ```
12 | or use the Contao Manager.
13 |
14 | ## Usage
15 | 1. Enable the built-in CSS grid in your Contao page layout settings or create your own custom CSS.
16 | 2. Add a new content element of type "Gridset Start". The corresponding "Gridset End" will be added automatically.
17 | 3. Configure your column settings in the "Gridset Start" element.
18 | 4. Place your desired content elements between the "Gridset Start" and "Gridset End" elements.
19 |
20 | If you need multiple content elements within a single column, wrap them with "Column Start" and "Column End" elements.
21 |
22 | ## Customized CSS
23 | To override the default grid styles:
24 | 1. Uncheck "Load Clickpress Grid CSS" in the page layout settings.
25 | 2. Copy and customize the clickpress-grid.scss file (https://github.com/clickpress/contao-clickpress-grid/blob/main/public/clickpress-grid.scss)
26 | 3. Include your custom CSS as an external stylesheet in the layout settings.
27 |
28 | ## Inside
29 | This is the result of a 40% 30% 30% setting on desktop. So, three columns will be displayed in a row. The fourth column will be placed in a new row, automatically.
30 | ```html
31 |
32 |
...
33 |
...
34 |
...
35 |
...
36 |
...
37 |
38 | ```
39 |
40 | ## Credits
41 | Big thanks to [rocksolid_columns](https://github.com/madeyourday/contao-rocksolid-columns) for some parts of the module.
42 |
--------------------------------------------------------------------------------
/src/Element/GridStop.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Element;
17 |
18 | use Contao\ContentModel;
19 | use Contao\CoreBundle\Controller\ContentElement\AbstractContentElementController;
20 | use Contao\CoreBundle\DependencyInjection\Attribute\AsContentElement;
21 | use Contao\CoreBundle\Routing\ScopeMatcher;
22 | use Contao\Template;
23 | use Symfony\Component\HttpFoundation\Request;
24 | use Symfony\Component\HttpFoundation\RequestStack;
25 | use Symfony\Component\HttpFoundation\Response;
26 |
27 | /**
28 | * Grid stop content element Taken with friendly permission from RockSolid Columns.
29 | */
30 | #[AsContentElement(type: 'cp_grid_stop', category: 'cp_grid', template: 'ce_grid_stop')]
31 | class GridStop extends AbstractContentElementController
32 | {
33 | public function __construct(readonly RequestStack $requestStack, readonly ScopeMatcher $scopeMatcher)
34 | {
35 | }
36 |
37 | protected function getResponse(Template $template, ContentModel $model, Request $request): Response
38 | {
39 | if ($this->scopeMatcher->isBackendRequest($this->requestStack->getCurrentRequest())) {
40 | return new Response('');
41 | }
42 |
43 | $parentKey = ($model->ptable ?: 'tl_article').'__'.$model->pid;
44 |
45 | if (isset($GLOBALS['TL_CP_GRID'][$parentKey])) {
46 | if (!$GLOBALS['TL_CP_GRID'][$parentKey]['active']) {
47 | trigger_error(
48 | 'Missing column stop element before column wrapper stop element ID '.$model->id.'.',
49 | E_USER_WARNING,
50 | );
51 | }
52 | unset($GLOBALS['TL_CP_GRID'][$parentKey]);
53 | }
54 |
55 | return $template->getResponse();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Forms/FormGridStart.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Forms;
17 |
18 | use Contao\BackendTemplate;
19 | use Contao\System;
20 | use Contao\Widget;
21 |
22 | /**
23 | * Grid start content element Taken with friendly permission from RockSolid Columns.
24 | */
25 | class FormGridStart extends Widget
26 | {
27 | /**
28 | * @var string Template
29 | */
30 | protected $strTemplate = 'form_grid_start';
31 |
32 | /**
33 | * Do not validate.
34 | */
35 | public function validate(): void
36 | {
37 | }
38 |
39 | /**
40 | * Parse the template file and return it as string.
41 | *
42 | * @param array $arrAttributes An optional attributes array
43 | *
44 | * @return string The template markup
45 | */
46 | public function parse($arrAttributes = null): string
47 | {
48 | $request = System::getContainer()->get('request_stack')->getCurrentRequest();
49 | if ($request && System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request)) {
50 | $objTemplate = new BackendTemplate('be_wildcard');
51 |
52 | return $objTemplate->parse();
53 | }
54 | $gridClasses = [
55 | str_replace('grid', 'grid_desktop', $this->form_cp_grid_desktop),
56 | str_replace('grid', 'grid_tablet', $this->form_cp_grid_tablet),
57 | str_replace('grid', 'grid_mobile', $this->form_cp_grid_mobile),
58 | ];
59 | $arrAttributes['gridClasses'] = implode(' ', $gridClasses);
60 |
61 | return parent::parse($arrAttributes);
62 | }
63 |
64 | /**
65 | * Generate the widget and return it as string.
66 | *
67 | * @return string The widget markup
68 | */
69 | public function generate(): string
70 | {
71 | return '';
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/contao/languages/en/tl_content.php:
--------------------------------------------------------------------------------
1 | '1 column',
28 | 'grid_50_50' => '2 columns',
29 | 'grid_33_33_33' => '3 columns',
30 | 'grid_25_25_25_25' => '4 columns',
31 | 'grid_20_20_20_20_20' => '5 columns',
32 | 'grid_16_16_16_16_16_16' => '6 columns',
33 | 'grid_75_25' => '2 columns - divided into 75% 25%',
34 | 'grid_25_75' => '2 columns - divided into 25% 75%',
35 | 'grid_66_33' => '2 columns - divided into 66% 33%',
36 | 'grid_33_66' => '2 columns - divided into 33% 66%',
37 | 'grid_60_40' => '2 columns - divided into 60% 40%',
38 | 'grid_40_60' => '2 columns - divided into 40% 60%',
39 | 'grid_50_25_25' => '3 columns - divided into 50% 25% 25%',
40 | 'grid_25_50_25' => '3 columns - divided into 25% 50% 25%',
41 | 'grid_25_25_50' => '3 columns - divided into 25% 25% 50%',
42 | 'grid_40_30_30' => '3 columns - divided into 40% 30% 30%',
43 | 'grid_30_40_30' => '3 columns - divided into 30% 40% 30%',
44 | 'grid_30_30_40' => '3 columns - divided into 30% 30% 40%',
45 | 'grid_20_40_40' => '3 columns - divided into 20% 40% 40%',
46 | 'grid_40_20_40' => '3 columns - divided into 40% 20% 40%',
47 | 'grid_40_40_20' => '3 columns - divided into 40% 40% 20%',
48 | 'grid_40_20_20_20' => '4 columns - divided into 40% 20% 20% 20%',
49 | 'grid_20_40_20_20' => '4 columns - divided into 20% 40% 20% 20%',
50 | 'grid_20_20_40_20' => '4 columns - divided into 20% 20% 40% 20%',
51 | 'grid_20_20_20_40' => '4 columns - divided into 20% 20% 20% 40%',
52 | ];
53 |
54 | $GLOBALS['TL_LANG']['tl_content']['cp_gap_options'] = [
55 | 'gap_0' => 'no gap',
56 | 'gap_1' => '1',
57 | 'gap_2' => '2',
58 | 'gap_3' => '3',
59 | 'gap_4' => '4',
60 | 'gap_5' => '5',
61 | 'gap_6' => '6',
62 | 'gap_7' => '7',
63 | 'gap_8' => '8',
64 | 'gap_9' => '9',
65 | 'gap_10' => '10',
66 | 'gap_11' => '11',
67 | 'gap_12' => '12',
68 | ];
69 |
70 | // Legend
71 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_legend'] = 'Column configuration';
72 |
--------------------------------------------------------------------------------
/contao/languages/de/tl_content.php:
--------------------------------------------------------------------------------
1 | 'oben',
34 | 'center' => 'zentriert',
35 | 'bottom' => 'unten',
36 | 'stretch' => 'strecken',
37 | 'baseline' => 'Grundlinie',
38 | ];
39 |
40 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_halign_options'] = [
41 | 'left' => 'links',
42 | 'center' => 'zentriert',
43 | 'right' => 'rechts',
44 | 'stretch' => 'strecken',
45 | ];
46 |
47 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_options'] = [
48 | 'grid_100' => '1 Spalte',
49 | 'grid_50_50' => '2 Spalten',
50 | 'grid_33_33_33' => '3 Spalten',
51 | 'grid_25_25_25_25' => '4 Spalten',
52 | 'grid_20_20_20_20_20' => '5 Spalten',
53 | 'grid_16_16_16_16_16_16' => '6 Spalten',
54 | 'grid_75_25' => '2 Spalten - aufgeteilt in 75% 25%',
55 | 'grid_25_75' => '2 Spalten - aufgeteilt in 25% 75%',
56 | 'grid_66_33' => '2 Spalten - aufgeteilt in 66% 33%',
57 | 'grid_33_66' => '2 Spalten - aufgeteilt in 33% 66%',
58 | 'grid_60_40' => '2 Spalten - aufgeteilt in 60% 40%',
59 | 'grid_40_60' => '2 Spalten - aufgeteilt in 40% 60%',
60 | 'grid_50_25_25' => '3 Spalten - aufgeteilt in 50% 25% 25%',
61 | 'grid_25_50_25' => '3 Spalten - aufgeteilt in 25% 50% 25%',
62 | 'grid_25_25_50' => '3 Spalten - aufgeteilt in 25% 25% 50%',
63 | 'grid_40_30_30' => '3 Spalten - aufgeteilt in 40% 30% 30%',
64 | 'grid_30_40_30' => '3 Spalten - aufgeteilt in 30% 40% 30%',
65 | 'grid_30_30_40' => '3 Spalten - aufgeteilt in 30% 30% 40%',
66 | 'grid_20_40_40' => '3 Spalten - aufgeteilt in 20% 40% 40%',
67 | 'grid_40_20_40' => '3 Spalten - aufgeteilt in 40% 20% 40%',
68 | 'grid_40_40_20' => '3 Spalten - aufgeteilt in 40% 40% 20%',
69 | 'grid_40_20_20_20' => '4 Spalten - aufgeteilt in 40% 20% 20% 20%',
70 | 'grid_20_40_20_20' => '4 Spalten - aufgeteilt in 20% 40% 20% 20%',
71 | 'grid_20_20_40_20' => '4 Spalten - aufgeteilt in 20% 20% 40% 20%',
72 | 'grid_20_20_20_40' => '4 Spalten - aufgeteilt in 20% 20% 20% 40%',
73 | ];
74 |
75 | $GLOBALS['TL_LANG']['tl_content']['cp_gap_options'] = [
76 | 'gap_0' => 'kein Abstand',
77 | 'gap_1' => '1',
78 | 'gap_2' => '2',
79 | 'gap_3' => '3',
80 | 'gap_4' => '4',
81 | 'gap_5' => '5',
82 | 'gap_6' => '6',
83 | 'gap_7' => '7',
84 | 'gap_8' => '8',
85 | 'gap_9' => '9',
86 | 'gap_10' => '10',
87 | 'gap_11' => '11',
88 | 'gap_12' => '12',
89 | ];
90 |
91 | // Legend
92 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_legend'] = 'Spalten-Konfiguration';
93 |
--------------------------------------------------------------------------------
/contao/dca/tl_form_field.php:
--------------------------------------------------------------------------------
1 | &$GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_desktop'],
14 | 'inputType' => 'select',
15 | 'options' => [
16 | 'grid_100',
17 | 'grid_50_50',
18 | 'grid_33_33_33',
19 | 'grid_25_25_25_25',
20 | 'grid_20_20_20_20_20',
21 | 'grid_75_25',
22 | 'grid_25_75',
23 | 'grid_66_33',
24 | 'grid_33_66',
25 | 'grid_60_40',
26 | 'grid_40_60',
27 | 'grid_50_25_25',
28 | 'grid_25_50_25',
29 | 'grid_25_25_50',
30 | 'grid_40_30_30',
31 | 'grid_30_40_30',
32 | 'grid_30_30_40',
33 | 'grid_20_40_40',
34 | 'grid_40_20_40',
35 | 'grid_40_40_20',
36 | 'grid_40_20_20_20',
37 | 'grid_20_40_20_20',
38 | 'grid_20_20_40_20',
39 | 'grid_20_20_20_40',
40 | ],
41 | 'reference' => &$GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_options'],
42 | 'eval' => [
43 | 'tl_class' => 'w33',
44 | ],
45 | 'sql' => "varchar(255) NOT NULL default ''",
46 | ];
47 |
48 | $GLOBALS['TL_DCA']['tl_form_field']['fields']['form_cp_grid_tablet'] = [
49 | 'label' => &$GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_tablet'],
50 | 'inputType' => 'select',
51 | 'options' => [
52 | 'grid_100',
53 | 'grid_50_50',
54 | 'grid_33_33_33',
55 | 'grid_25_25_25_25',
56 | 'grid_75_25',
57 | 'grid_25_75',
58 | 'grid_66_33',
59 | 'grid_33_66',
60 | 'grid_50_25_25',
61 | 'grid_25_50_25',
62 | 'grid_25_25_50',
63 | 'grid_40_30_30',
64 | 'grid_30_40_30',
65 | 'grid_30_30_40',
66 | 'grid_20_40_40',
67 | 'grid_40_20_40',
68 | 'grid_40_40_20',
69 | ],
70 | 'reference' => &$GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_options'],
71 | 'eval' => [
72 | 'tl_class' => 'w33',
73 | ],
74 | 'sql' => "varchar(255) NOT NULL default ''",
75 | ];
76 |
77 | $GLOBALS['TL_DCA']['tl_form_field']['fields']['form_cp_grid_mobile'] = [
78 | 'label' => &$GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_mobile'],
79 | 'inputType' => 'select',
80 | 'options' => [
81 | 'grid_100',
82 | 'grid_50_50',
83 | 'grid_33_33_33',
84 | 'grid_25_25_25_25',
85 | 'grid_75_25',
86 | 'grid_25_75',
87 | 'grid_66_33',
88 | 'grid_33_66',
89 | 'grid_50_25_25',
90 | 'grid_25_50_25',
91 | 'grid_25_25_50',
92 | 'grid_40_30_30',
93 | 'grid_30_40_30',
94 | 'grid_30_30_40',
95 | ],
96 | 'reference' => &$GLOBALS['TL_LANG']['tl_form_field']['form_cp_grid_options'],
97 | 'eval' => [
98 | 'tl_class' => 'w33',
99 | ],
100 | 'sql' => "varchar(255) NOT NULL default ''",
101 | ];
102 |
--------------------------------------------------------------------------------
/src/EventListener/ClickpressGridListener.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\EventListener;
17 |
18 | use Contao\CoreBundle\DependencyInjection\Attribute\AsCallback;
19 | use Contao\CoreBundle\DependencyInjection\Attribute\AsHook;
20 | use Contao\Database;
21 | use Contao\DataContainer;
22 | use Contao\LayoutModel;
23 | use Contao\PageModel;
24 | use Contao\PageRegular;
25 |
26 | /**
27 | * ClickpressGridListener Taken with friendly permission from RockSolid Columns.
28 | *
29 | * Provide miscellaneous methods that are used by the data configuration arrays.
30 | */
31 | class ClickpressGridListener
32 | {
33 | #[AsHook('generatePage')]
34 | public function onGeneratePage(PageModel $pageModel, LayoutModel $layout, PageRegular $pageRegular): void
35 | {
36 | if ($layout->cp_grid_load_css) {
37 | $GLOBALS['TL_CSS'][] = 'bundles/contaoclickpressgrid/clickpress-grid.css||static';
38 | }
39 | }
40 |
41 | /**
42 | * tl_content DCA onsubmit callback.
43 | *
44 | * Creates a stop element after a start element was created
45 | */
46 | #[AsCallback(table: 'tl_content', target: 'config.onsubmit')]
47 | public function onsubmitCallback(DataContainer $dc): void
48 | {
49 | $activeRecord = $dc->activeRecord;
50 | if (!$activeRecord) {
51 | return;
52 | }
53 |
54 | if ('cp_grid_start' === $activeRecord->type || 'cp_column_start' === $activeRecord->type) {
55 | // Find the next columns or column element
56 | $nextElement = Database::getInstance()
57 | ->prepare('
58 | SELECT type
59 | FROM tl_content
60 | WHERE pid = ?
61 | AND (ptable = ? OR ptable = ?)
62 | AND type IN (\'cp_column_start\', \'cp_column_stop\', \'cp_grid_start\', \'cp_grid_stop\')
63 | AND sorting > ?
64 | ORDER BY sorting
65 | LIMIT 1
66 | ')
67 | ->execute(
68 | $activeRecord->pid,
69 | $activeRecord->ptable ?: 'tl_article',
70 | 'tl_article' === $activeRecord->ptable ? '' : $activeRecord->ptable,
71 | $activeRecord->sorting,
72 | )
73 | ;
74 |
75 | // Check if a stop element should be created
76 | if (
77 | !$nextElement->type
78 | || ('cp_grid_start' === $activeRecord->type && 'cp_column_stop' === $nextElement->type)
79 | || ('cp_column_start' === $activeRecord->type && (
80 | 'cp_column_start' === $nextElement->type || 'cp_grid_stop' === $nextElement->type
81 | ))
82 | ) {
83 | $set = [];
84 |
85 | // Get all default values for the new entry
86 | foreach ($GLOBALS['TL_DCA']['tl_content']['fields'] as $field => $config) {
87 | if (\array_key_exists('default', $config)) {
88 | $set[$field] = \is_array($config['default']) ? serialize($config['default']) : $config['default'];
89 | }
90 | }
91 |
92 | $set['pid'] = $activeRecord->pid;
93 | $set['ptable'] = $activeRecord->ptable ?: 'tl_article';
94 | $set['type'] = substr($activeRecord->type, 0, -5).'stop';
95 | $set['sorting'] = $activeRecord->sorting + 1;
96 | $set['invisible'] = $activeRecord->invisible;
97 | $set['start'] = $activeRecord->start;
98 | $set['stop'] = $activeRecord->stop;
99 | $set['tstamp'] = time();
100 |
101 | Database::getInstance()
102 | ->prepare('INSERT INTO tl_content %s')
103 | ->set($set)
104 | ->execute()
105 | ;
106 | }
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/Element/GridStart.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Martin Auswöger
10 | * @author Jannik Nölke
11 | *
12 | * For the full copyright and license information, please view the LICENSE
13 | * file that was distributed with this source code.
14 | */
15 |
16 | namespace Clickpress\ContaoClickpressGridBundle\Element;
17 |
18 | use Contao\ContentModel;
19 | use Contao\CoreBundle\Controller\ContentElement\AbstractContentElementController;
20 | use Contao\CoreBundle\DependencyInjection\Attribute\AsContentElement;
21 | use Contao\CoreBundle\Routing\ScopeMatcher;
22 | use Contao\StringUtil;
23 | use Contao\System;
24 | use Contao\Template;
25 | use Symfony\Component\HttpFoundation\Request;
26 | use Symfony\Component\HttpFoundation\RequestStack;
27 | use Symfony\Component\HttpFoundation\Response;
28 |
29 | /**
30 | * Grid start content element Taken with friendly permission from RockSolid Columns.
31 | */
32 | #[AsContentElement(type: 'cp_grid_start', category: 'cp_grid', template: 'ce_grid_start')]
33 | class GridStart extends AbstractContentElementController
34 | {
35 | public function __construct(readonly RequestStack $requestStack, readonly ScopeMatcher $scopeMatcher)
36 | {
37 | }
38 |
39 | /**
40 | * Generate the columns classes.
41 | *
42 | * @param array $data Data array
43 | */
44 | public static function getColumnsConfiguration(array $data): array
45 | {
46 | $config = [];
47 |
48 | foreach (['desktop', 'tablet', 'mobile'] as $media) {
49 | $mediaClass = 'cp_grid_' . $media;
50 | if (isset($data[$mediaClass])) {
51 | $columns = str_replace('grid', 'grid_' . $media, $data['cp_grid_' . $media]);
52 | $config[$media] = $columns;
53 | } else {
54 | $config[$media] = null;
55 | }
56 | }
57 |
58 | return $config;
59 | }
60 |
61 | /**
62 | * Generate the device-specific class based on gap presence and type.
63 | *
64 | * @param string $deviceType Type of the device (e.g., desktop, tablet, mobile)
65 | * @param mixed $gap Gap information (can be any type depending on its usage)
66 | *
67 | * @return string Generated device class
68 | */
69 | public function generateGapClass(string $deviceType, string $gap): string
70 | {
71 | $gapArray = explode('_', $gap);
72 |
73 | return $gap ? " {$gapArray[0]}_{$deviceType}_{$gapArray[1]} " : '';
74 | }
75 |
76 | protected function getResponse(Template $template, ContentModel $model, Request $request): Response
77 | {
78 | if ($this->scopeMatcher->isBackendRequest($this->requestStack->getCurrentRequest())) {
79 | $listingTitle = '';
80 |
81 | if($model->headline) {
82 | $headline = StringUtil::deserialize($model->headline, true);
83 | $listingTitle = $headline['value'];
84 | }
85 |
86 | if($model->title) {
87 | $listingTitle = $model->title;
88 | }
89 |
90 | return new Response($listingTitle. "
" . $this->getConfigInfo($model));
91 | }
92 |
93 | $template->gridClasses = '';
94 |
95 | $parentKey = ($model->ptable ?: 'tl_article') . '__' . $model->pid;
96 |
97 | $GLOBALS['TL_CP_GRID'][$parentKey] = [
98 | 'active' => true,
99 | 'count' => 0,
100 | 'config' => static::getColumnsConfiguration($model->row()),
101 | ];
102 | $template->gridClasses = implode(' ', $GLOBALS['TL_CP_GRID'][$parentKey]['config']);
103 |
104 | if ($model->cp_grid_valign) {
105 | $template->gridClasses .= ' ' . $model->cp_grid_valign;
106 | }
107 |
108 | if ($model->cp_grid_halign) {
109 | $template->gridClasses .= ' ' . $model->cp_grid_halign;
110 | }
111 |
112 | $template->gridClasses .= $model->cp_gap_mobile ? $this->generateGapClass('mobile', $model->cp_gap_mobile) : '';
113 | $template->gridClasses .= $model->cp_gap_tablet ? $this->generateGapClass('tablet', $model->cp_gap_tablet) : '';
114 | $template->gridClasses .= $model->cp_gap_desktop ? $this->generateGapClass(
115 | 'desktop',
116 | $model->cp_gap_desktop
117 | ) : '';
118 |
119 | return $template->getResponse();
120 | }
121 |
122 | /**
123 | * Generates a configuration information string for the given content model.
124 | *
125 | * @param ContentModel $model the content model containing configuration information
126 | *
127 | * @return string the formatted configuration information string
128 | */
129 | private function getConfigInfo(ContentModel $model): string
130 | {
131 | System::loadLanguageFile('tl_content');
132 |
133 | $configInfo = '';
134 |
135 | $configInfo .= \sprintf(
136 | '%s: %s %s, ',
137 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_mobile'][0],
138 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_options'][$model->cp_grid_mobile],
139 | isset($model->cp_gap_mobile) ? $this->formatGapOption($model->cp_gap_mobile) : '',
140 | );
141 |
142 | $configInfo .= \sprintf(
143 | '%s: %s %s, ',
144 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_tablet'][0],
145 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_options'][$model->cp_grid_tablet],
146 | isset($model->cp_gap_tablet) ? $this->formatGapOption($model->cp_gap_tablet) : '',
147 | );
148 |
149 | $configInfo .= \sprintf(
150 | '%s: %s %s, ',
151 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_desktop'][0],
152 | $GLOBALS['TL_LANG']['tl_content']['cp_grid_options'][$model->cp_grid_desktop],
153 | isset($model->cp_gap_desktop) ? $this->formatGapOption($model->cp_gap_desktop) : '',
154 | );
155 |
156 | $configInfo .= '';
157 |
158 | return $configInfo;
159 | }
160 |
161 | /**
162 | * Format Gap Option.
163 | */
164 | private function formatGapOption(string $gap): string
165 | {
166 | return !empty($gap) ? '(' . $GLOBALS['TL_LANG']['tl_content']['cp_gap_options'][$gap] . ')' : '';
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/contao/dca/tl_content.php:
--------------------------------------------------------------------------------
1 | =') ) {
18 | PaletteManipulator::create()
19 | ->addField('title', 'headline', PaletteManipulator::POSITION_BEFORE)
20 | ->applyToPalette('cp_grid_start', 'tl_content')
21 | ->applyToPalette('cp_grid_stop', 'tl_content')
22 | ->applyToPalette('cp_column_start', 'tl_content')
23 | ->applyToPalette('cp_column_stop', 'tl_content')
24 | ;
25 | }
26 |
27 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_grid_desktop'] = [
28 | 'label' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_desktop'],
29 | 'inputType' => 'select',
30 | 'options' => [
31 | 'grid_100',
32 | 'grid_50_50',
33 | 'grid_33_33_33',
34 | 'grid_25_25_25_25',
35 | 'grid_20_20_20_20_20',
36 | 'grid_16_16_16_16_16_16',
37 | 'grid_75_25',
38 | 'grid_25_75',
39 | 'grid_66_33',
40 | 'grid_33_66',
41 | 'grid_60_40',
42 | 'grid_40_60',
43 | 'grid_50_25_25',
44 | 'grid_25_50_25',
45 | 'grid_25_25_50',
46 | 'grid_40_30_30',
47 | 'grid_30_40_30',
48 | 'grid_30_30_40',
49 | 'grid_20_40_40',
50 | 'grid_40_20_40',
51 | 'grid_40_40_20',
52 | 'grid_40_20_20_20',
53 | 'grid_20_40_20_20',
54 | 'grid_20_20_40_20',
55 | 'grid_20_20_20_40',
56 | ],
57 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_options'],
58 | 'eval' => [
59 | 'tl_class' => 'w33',
60 | ],
61 | 'sql' => "varchar(255) NOT NULL default ''",
62 | ];
63 |
64 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_grid_tablet'] = [
65 | 'label' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_tablet'],
66 | 'inputType' => 'select',
67 | 'options' => [
68 | 'grid_100',
69 | 'grid_50_50',
70 | 'grid_33_33_33',
71 | 'grid_25_25_25_25',
72 | 'grid_75_25',
73 | 'grid_25_75',
74 | 'grid_66_33',
75 | 'grid_33_66',
76 | 'grid_60_40',
77 | 'grid_40_60',
78 | 'grid_50_25_25',
79 | 'grid_25_50_25',
80 | 'grid_25_25_50',
81 | 'grid_40_30_30',
82 | 'grid_30_40_30',
83 | 'grid_30_30_40',
84 | 'grid_20_40_40',
85 | 'grid_40_20_40',
86 | 'grid_40_40_20',
87 | ],
88 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_options'],
89 | 'eval' => [
90 | 'tl_class' => 'w33',
91 | ],
92 | 'sql' => "varchar(255) NOT NULL default ''",
93 | ];
94 |
95 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_grid_mobile'] = [
96 | 'label' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_mobile'],
97 | 'inputType' => 'select',
98 | 'options' => [
99 | 'grid_100',
100 | 'grid_50_50',
101 | 'grid_33_33_33',
102 | 'grid_25_25_25_25',
103 | 'grid_75_25',
104 | 'grid_25_75',
105 | 'grid_66_33',
106 | 'grid_33_66',
107 | 'grid_60_40',
108 | 'grid_40_60',
109 | 'grid_50_25_25',
110 | 'grid_25_50_25',
111 | 'grid_25_25_50',
112 | 'grid_40_30_30',
113 | 'grid_30_40_30',
114 | 'grid_30_30_40',
115 | ],
116 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_options'],
117 | 'eval' => [
118 | 'tl_class' => 'w33',
119 | ],
120 | 'sql' => "varchar(255) NOT NULL default ''",
121 | ];
122 |
123 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_gap_mobile'] = [
124 | 'inputType' => 'select',
125 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_gap_options'],
126 | 'default' => '',
127 | 'options' => [
128 | 'gap_0',
129 | 'gap_1',
130 | 'gap_2',
131 | 'gap_3',
132 | 'gap_4',
133 | 'gap_5',
134 | 'gap_6',
135 | 'gap_7',
136 | 'gap_8',
137 | 'gap_9',
138 | 'gap_10',
139 | 'gap_11',
140 | 'gap_12',
141 | ],
142 | 'eval' => [
143 | 'includeBlankOption' => true,
144 | 'blankOptionLabel' => '-',
145 | 'tl_class' => 'w33',
146 | ],
147 | 'sql' => "varchar(255) NOT NULL default ''",
148 | ];
149 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_gap_tablet'] = [
150 | 'inputType' => 'select',
151 | 'default' => '',
152 | 'options' => [
153 | 'gap_0',
154 | 'gap_1',
155 | 'gap_2',
156 | 'gap_3',
157 | 'gap_4',
158 | 'gap_5',
159 | 'gap_6',
160 | 'gap_7',
161 | 'gap_8',
162 | 'gap_9',
163 | 'gap_10',
164 | 'gap_11',
165 | 'gap_12',
166 | ],
167 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_gap_options'],
168 | 'eval' => [
169 | 'includeBlankOption' => true,
170 | 'blankOptionLabel' => '-',
171 | 'tl_class' => 'w33',
172 | ],
173 | 'sql' => "varchar(255) NOT NULL default ''",
174 | ];
175 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_gap_desktop'] = [
176 | 'inputType' => 'select',
177 | 'default' => '',
178 | 'options' => [
179 | 'gap_0',
180 | 'gap_1',
181 | 'gap_2',
182 | 'gap_3',
183 | 'gap_4',
184 | 'gap_5',
185 | 'gap_6',
186 | 'gap_7',
187 | 'gap_8',
188 | 'gap_9',
189 | 'gap_10',
190 | 'gap_11',
191 | 'gap_12',
192 | ],
193 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_gap_options'],
194 | 'eval' => [
195 | 'includeBlankOption' => true,
196 | 'blankOptionLabel' => '-',
197 | 'tl_class' => 'w33',
198 | ],
199 | 'sql' => "varchar(255) NOT NULL default ''",
200 | ];
201 |
202 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_grid_valign'] = [
203 | 'inputType' => 'select',
204 | 'default' => false,
205 | 'options' => [
206 | 'items-start' => 'top',
207 | 'items-center' => 'center',
208 | 'items-end' => 'bottom',
209 | 'items-stretch' => 'stretch',
210 | 'items-baseline' => 'baseline',
211 | ],
212 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_valign_options'],
213 | 'eval' => [
214 | 'tl_class' => 'w50 m12 clr',
215 | 'includeBlankOption' => true,
216 | ],
217 | 'sql' => "varchar(255) NOT NULL default ''",
218 | ];
219 |
220 | $GLOBALS['TL_DCA']['tl_content']['fields']['cp_grid_halign'] = [
221 | 'inputType' => 'select',
222 | 'default' => false,
223 | 'options' => [
224 | 'justify-items-start' => 'left',
225 | 'justify-items-center' => 'center',
226 | 'justify-items-end' => 'right',
227 | 'justify-items-stretch' => 'stretch',
228 | ],
229 | 'reference' => &$GLOBALS['TL_LANG']['tl_content']['cp_grid_halign_options'],
230 | 'eval' => [
231 | 'tl_class' => 'w50 m12',
232 | 'includeBlankOption' => true,
233 | ],
234 | 'sql' => "varchar(255) NOT NULL default ''",
235 | ];
236 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/public/clickpress-grid.css:
--------------------------------------------------------------------------------
1 | /**
2 | * CLICKPRESS CSS-Grid
3 | * @author: Stefan Schulz-Lauterbach
4 | *
5 | * thanks to Dinko Skopljak for co-working
6 | */
7 | .justify-items-start {
8 | justify-items: start;
9 | }
10 |
11 | .justify-items-center {
12 | justify-items: center;
13 | }
14 |
15 | .justify-items-end {
16 | justify-items: end;
17 | }
18 |
19 | .justify-items-stretch {
20 | justify-items: stretch;
21 | }
22 |
23 | .content-start {
24 | align-content: start;
25 | }
26 |
27 | .content-center {
28 | align-content: center;
29 | }
30 |
31 | .content-end {
32 | align-content: end;
33 | }
34 |
35 | .items-start {
36 | align-items: start;
37 | }
38 |
39 | .items-center {
40 | align-items: center;
41 | }
42 |
43 | .items-end {
44 | align-items: end;
45 | }
46 |
47 | .items-stretch {
48 | align-items: stretch;
49 | }
50 |
51 | .items-baseline {
52 | align-items: baseline;
53 | }
54 |
55 | [class*=grid_] {
56 | display: grid !important;
57 | grid-gap: 1rem;
58 | }
59 | [class*=grid_] > .block {
60 | margin-bottom: 0;
61 | }
62 |
63 | .ce_cp_column_start:has(.content-swiper) {
64 | overflow: hidden;
65 | }
66 |
67 | @media (min-width: 576px) {
68 | .grid_mobile_100 {
69 | grid-template-columns: 1fr;
70 | }
71 | .grid_mobile_50_50 {
72 | grid-template-columns: repeat(2, 1fr);
73 | }
74 | .grid_mobile_33_33_33 {
75 | grid-template-columns: repeat(3, 1fr);
76 | }
77 | .grid_mobile_25_25_25_25 {
78 | grid-template-columns: repeat(4, 1fr);
79 | }
80 | .grid_mobile_75_25 {
81 | grid-template-columns: 3fr 1fr;
82 | }
83 | .grid_mobile_25_75 {
84 | grid-template-columns: 1fr 3fr;
85 | }
86 | .grid_mobile_66_33 {
87 | grid-template-columns: 2fr 1fr;
88 | }
89 | .grid_mobile_33_66 {
90 | grid-template-columns: 1fr 2fr;
91 | }
92 | .grid_mobile_60_40 {
93 | grid-template-columns: 3fr 2fr;
94 | }
95 | .grid_mobile_40_60 {
96 | grid-template-columns: 2fr 3fr;
97 | }
98 | .grid_mobile_50_25_25 {
99 | grid-template-columns: 2fr 1fr 1fr;
100 | }
101 | .grid_mobile_25_50_25 {
102 | grid-template-columns: 1fr 2fr 1fr;
103 | }
104 | .grid_mobile_25_25_50 {
105 | grid-template-columns: 1fr 1fr 2fr;
106 | }
107 | .grid_mobile_40_30_30 {
108 | grid-template-columns: 4fr 3fr 3fr;
109 | }
110 | .grid_mobile_30_40_30 {
111 | grid-template-columns: 3fr 4fr 3fr;
112 | }
113 | .grid_mobile_30_30_40 {
114 | grid-template-columns: 3fr 3fr 4fr;
115 | }
116 | .gap_mobile_0 {
117 | grid-gap: 0;
118 | }
119 | .gap_mobile_1 {
120 | grid-gap: 1rem;
121 | }
122 | .gap_mobile_2 {
123 | grid-gap: 2rem;
124 | }
125 | .gap_mobile_3 {
126 | grid-gap: 3rem;
127 | }
128 | .gap_mobile_4 {
129 | grid-gap: 4rem;
130 | }
131 | .gap_mobile_5 {
132 | grid-gap: 5rem;
133 | }
134 | .gap_mobile_6 {
135 | grid-gap: 6rem;
136 | }
137 | .gap_mobile_7 {
138 | grid-gap: 7rem;
139 | }
140 | .gap_mobile_8 {
141 | grid-gap: 8rem;
142 | }
143 | .gap_mobile_9 {
144 | grid-gap: 9rem;
145 | }
146 | .gap_mobile_10 {
147 | grid-gap: 10rem;
148 | }
149 | .gap_mobile_11 {
150 | grid-gap: 11rem;
151 | }
152 | .gap_mobile_12 {
153 | grid-gap: 12rem;
154 | }
155 | }
156 | @media (min-width: 768px) {
157 | .grid_tablet_100 {
158 | grid-template-columns: 1fr;
159 | }
160 | .grid_tablet_50_50 {
161 | grid-template-columns: repeat(2, 1fr);
162 | }
163 | .grid_tablet_33_33_33 {
164 | grid-template-columns: repeat(3, 1fr);
165 | }
166 | .grid_tablet_25_25_25_25 {
167 | grid-template-columns: repeat(4, 1fr);
168 | }
169 | .grid_tablet_75_25 {
170 | grid-template-columns: 3fr 1fr;
171 | }
172 | .grid_tablet_25_75 {
173 | grid-template-columns: 1fr 3fr;
174 | }
175 | .grid_tablet_66_33 {
176 | grid-template-columns: 2fr 1fr;
177 | }
178 | .grid_tablet_33_66 {
179 | grid-template-columns: 1fr 2fr;
180 | }
181 | .grid_tablet_60_40 {
182 | grid-template-columns: 3fr 2fr;
183 | }
184 | .grid_tablet_40_60 {
185 | grid-template-columns: 2fr 3fr;
186 | }
187 | .grid_tablet_50_25_25 {
188 | grid-template-columns: 2fr 1fr 1fr;
189 | }
190 | .grid_tablet_25_50_25 {
191 | grid-template-columns: 1fr 2fr 1fr;
192 | }
193 | .grid_tablet_25_25_50 {
194 | grid-template-columns: 1fr 1fr 2fr;
195 | }
196 | .grid_tablet_40_30_30 {
197 | grid-template-columns: 4fr 3fr 3fr;
198 | }
199 | .grid_tablet_30_40_30 {
200 | grid-template-columns: 3fr 4fr 3fr;
201 | }
202 | .grid_tablet_30_30_40 {
203 | grid-template-columns: 3fr 3fr 4fr;
204 | }
205 | .grid_tablet_20_40_40 {
206 | grid-template-columns: 1fr 2fr 2fr;
207 | }
208 | .grid_tablet_40_20_40 {
209 | grid-template-columns: 2fr 1fr 2fr;
210 | }
211 | .grid_tablet_40_40_20 {
212 | grid-template-columns: 2fr 2fr 1fr;
213 | }
214 | .gap_tablet_0 {
215 | grid-gap: 0;
216 | }
217 | .gap_tablet_1 {
218 | grid-gap: 1rem;
219 | }
220 | .gap_tablet_2 {
221 | grid-gap: 2rem;
222 | }
223 | .gap_tablet_3 {
224 | grid-gap: 3rem;
225 | }
226 | .gap_tablet_4 {
227 | grid-gap: 4rem;
228 | }
229 | .gap_tablet_5 {
230 | grid-gap: 5rem;
231 | }
232 | .gap_tablet_6 {
233 | grid-gap: 6rem;
234 | }
235 | .gap_tablet_7 {
236 | grid-gap: 7rem;
237 | }
238 | .gap_tablet_8 {
239 | grid-gap: 8rem;
240 | }
241 | .gap_tablet_9 {
242 | grid-gap: 9rem;
243 | }
244 | .gap_tablet_10 {
245 | grid-gap: 10rem;
246 | }
247 | .gap_tablet_11 {
248 | grid-gap: 11rem;
249 | }
250 | .gap_tablet_12 {
251 | grid-gap: 12rem;
252 | }
253 | }
254 | @media (min-width: 992px) {
255 | .grid_desktop_100 {
256 | grid-template-columns: 1fr;
257 | }
258 | .grid_desktop_50_50 {
259 | grid-template-columns: repeat(2, 1fr);
260 | }
261 | .grid_desktop_50_25_25 {
262 | grid-template-columns: 2fr 1fr 1fr;
263 | }
264 | .grid_desktop_33_33_33 {
265 | grid-template-columns: repeat(3, 1fr);
266 | }
267 | .grid_desktop_75_25 {
268 | grid-template-columns: 3fr 1fr;
269 | }
270 | .grid_desktop_25_75 {
271 | grid-template-columns: 1fr 3fr;
272 | }
273 | .grid_desktop_66_33 {
274 | grid-template-columns: 2fr 1fr;
275 | }
276 | .grid_desktop_60_40 {
277 | grid-template-columns: 3fr 2fr;
278 | }
279 | .grid_desktop_40_60 {
280 | grid-template-columns: 2fr 3fr;
281 | }
282 | .grid_desktop_33_66 {
283 | grid-template-columns: 1fr 2fr;
284 | }
285 | .grid_desktop_50_25_25 {
286 | grid-template-columns: 2fr 1fr 1fr;
287 | }
288 | .grid_desktop_40_30_30 {
289 | grid-template-columns: 4fr 3fr 3fr;
290 | }
291 | .grid_desktop_50_25_25 {
292 | grid-template-columns: 2fr 1fr 1fr;
293 | }
294 | .grid_desktop_25_50_25 {
295 | grid-template-columns: 1fr 2fr 1fr;
296 | }
297 | .grid_desktop_25_25_50 {
298 | grid-template-columns: 1fr 1fr 2fr;
299 | }
300 | .grid_desktop_40_30_30 {
301 | grid-template-columns: 4fr 3fr 3fr;
302 | }
303 | .grid_desktop_30_40_30 {
304 | grid-template-columns: 3fr 4fr 3fr;
305 | }
306 | .grid_desktop_30_30_40 {
307 | grid-template-columns: 3fr 3fr 4fr;
308 | }
309 | .grid_desktop_20_40_40 {
310 | grid-template-columns: 1fr 2fr 2fr;
311 | }
312 | .grid_desktop_40_20_40 {
313 | grid-template-columns: 2fr 1fr 2fr;
314 | }
315 | .grid_desktop_40_40_20 {
316 | grid-template-columns: 2fr 2fr 1fr;
317 | }
318 | .grid_desktop_25_25_25_25 {
319 | grid-template-columns: repeat(4, 1fr);
320 | }
321 | .grid_desktop_40_20_20_20 {
322 | grid-template-columns: 2fr 1fr 1fr 1fr;
323 | }
324 | .grid_desktop_20_40_20_20 {
325 | grid-template-columns: 1fr 2fr 1fr 1fr;
326 | }
327 | .grid_desktop_20_20_40_20 {
328 | grid-template-columns: 1fr 1fr 2fr 1fr;
329 | }
330 | .grid_desktop_20_20_20_40 {
331 | grid-template-columns: 1fr 1fr 1fr 2fr;
332 | }
333 | .grid_desktop_20_20_20_20_20 {
334 | grid-template-columns: repeat(5, 1fr);
335 | }
336 | .grid_desktop_16_16_16_16_16_16 {
337 | grid-template-columns: repeat(6, 1fr);
338 | }
339 | .gap_desktop_0 {
340 | grid-gap: 0;
341 | }
342 | .gap_desktop_1 {
343 | grid-gap: 1rem;
344 | }
345 | .gap_desktop_2 {
346 | grid-gap: 2rem;
347 | }
348 | .gap_desktop_3 {
349 | grid-gap: 3rem;
350 | }
351 | .gap_desktop_4 {
352 | grid-gap: 4rem;
353 | }
354 | .gap_desktop_5 {
355 | grid-gap: 5rem;
356 | }
357 | .gap_desktop_6 {
358 | grid-gap: 6rem;
359 | }
360 | .gap_desktop_7 {
361 | grid-gap: 7rem;
362 | }
363 | .gap_desktop_8 {
364 | grid-gap: 8rem;
365 | }
366 | .gap_desktop_9 {
367 | grid-gap: 9rem;
368 | }
369 | .gap_desktop_10 {
370 | grid-gap: 10rem;
371 | }
372 | .gap_desktop_11 {
373 | grid-gap: 11rem;
374 | }
375 | .gap_desktop_12 {
376 | grid-gap: 12rem;
377 | }
378 | }
379 |
380 | /*# sourceMappingURL=clickpress-grid.css.map */
381 |
--------------------------------------------------------------------------------
/public/clickpress-grid.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * CLICKPRESS CSS-Grid
3 | * @author: Stefan Schulz-Lauterbach
4 | *
5 | * thanks to Dinko Skopljak for co-working
6 | */
7 | //
8 | // Media Queries
9 | // ---------
10 | $mq_small: 576px; // Small devices (landscape phones)
11 | $mq_medium: 768px; // Medium devices (tablets, 768px and up)
12 | $mq_large: 992px; // Large devices (desktops, 992px and up)
13 | $mq_extra: 1260px; // Extra large devices (large desktops, 1260px and up)
14 |
15 | // Alignment utilities
16 | .justify-items-start {
17 | justify-items: start;
18 | }
19 |
20 | .justify-items-center {
21 | justify-items: center;
22 | }
23 |
24 | .justify-items-end {
25 | justify-items: end;
26 | }
27 |
28 | .justify-items-stretch {
29 | justify-items: stretch;
30 | }
31 |
32 | .content-start {
33 | align-content: start;
34 | }
35 |
36 | .content-center {
37 | align-content: center;
38 | }
39 |
40 | .content-end {
41 | align-content: end;
42 | }
43 |
44 | .items-start {
45 | align-items: start;
46 | }
47 |
48 | .items-center {
49 | align-items: center;
50 | }
51 |
52 | .items-end {
53 | align-items: end;
54 | }
55 |
56 | .items-stretch {
57 | align-items: stretch;
58 | }
59 |
60 | .items-baseline {
61 | align-items: baseline;
62 | }
63 |
64 | [class*="grid_"] {
65 | display: grid !important;
66 | grid-gap: 1rem;
67 |
68 | > .block {
69 | margin-bottom: 0;
70 | }
71 | }
72 |
73 | .ce_cp_column_start:has(.content-swiper) {
74 | overflow: hidden;
75 | }
76 |
77 | @media (min-width: $mq_small) {
78 | .grid_mobile_100 {
79 | grid-template-columns: 1fr;
80 | }
81 | .grid_mobile_50_50 {
82 | grid-template-columns: repeat(2, 1fr);
83 | }
84 | .grid_mobile_33_33_33 {
85 | grid-template-columns: repeat(3, 1fr);
86 | }
87 | .grid_mobile_25_25_25_25 {
88 | grid-template-columns: repeat(4, 1fr);
89 | }
90 | .grid_mobile_75_25 {
91 | grid-template-columns: 3fr 1fr;
92 | }
93 | .grid_mobile_25_75 {
94 | grid-template-columns: 1fr 3fr;
95 | }
96 | .grid_mobile_66_33 {
97 | grid-template-columns: 2fr 1fr;
98 | }
99 | .grid_mobile_33_66 {
100 | grid-template-columns: 1fr 2fr;
101 | }
102 | .grid_mobile_60_40 {
103 | grid-template-columns: 3fr 2fr;
104 | }
105 | .grid_mobile_40_60 {
106 | grid-template-columns: 2fr 3fr;
107 | }
108 | .grid_mobile_50_25_25 {
109 | grid-template-columns: 2fr 1fr 1fr;
110 | }
111 | .grid_mobile_25_50_25 {
112 | grid-template-columns: 1fr 2fr 1fr;
113 | }
114 | .grid_mobile_25_25_50 {
115 | grid-template-columns: 1fr 1fr 2fr;
116 | }
117 | .grid_mobile_40_30_30 {
118 | grid-template-columns: 4fr 3fr 3fr;
119 | }
120 | .grid_mobile_30_40_30 {
121 | grid-template-columns: 3fr 4fr 3fr;
122 | }
123 | .grid_mobile_30_30_40 {
124 | grid-template-columns: 3fr 3fr 4fr;
125 | }
126 | .gap_mobile_0 {
127 | grid-gap: 0;
128 | }
129 | .gap_mobile_1 {
130 | grid-gap: 1rem;
131 | }
132 | .gap_mobile_2 {
133 | grid-gap: 2rem;
134 | }
135 | .gap_mobile_3 {
136 | grid-gap: 3rem;
137 | }
138 | .gap_mobile_4 {
139 | grid-gap: 4rem;
140 | }
141 | .gap_mobile_5 {
142 | grid-gap: 5rem;
143 | }
144 | .gap_mobile_6 {
145 | grid-gap: 6rem;
146 | }
147 | .gap_mobile_7 {
148 | grid-gap: 7rem;
149 | }
150 | .gap_mobile_8 {
151 | grid-gap: 8rem;
152 | }
153 | .gap_mobile_9 {
154 | grid-gap: 9rem;
155 | }
156 | .gap_mobile_10 {
157 | grid-gap: 10rem;
158 | }
159 | .gap_mobile_11 {
160 | grid-gap: 11rem;
161 | }
162 | .gap_mobile_12 {
163 | grid-gap: 12rem;
164 | }
165 | }
166 |
167 | @media (min-width: $mq_medium) {
168 | .grid_tablet_100 {
169 | grid-template-columns: 1fr;
170 | }
171 | .grid_tablet_50_50 {
172 | grid-template-columns: repeat(2, 1fr);
173 | }
174 | .grid_tablet_33_33_33 {
175 | grid-template-columns: repeat(3, 1fr)
176 | }
177 | .grid_tablet_25_25_25_25 {
178 | grid-template-columns: repeat(4, 1fr)
179 | }
180 | .grid_tablet_75_25 {
181 | grid-template-columns: 3fr 1fr;
182 | }
183 | .grid_tablet_25_75 {
184 | grid-template-columns: 1fr 3fr;
185 | }
186 | .grid_tablet_66_33 {
187 | grid-template-columns: 2fr 1fr;
188 | }
189 | .grid_tablet_33_66 {
190 | grid-template-columns: 1fr 2fr;
191 | }
192 | .grid_tablet_60_40 {
193 | grid-template-columns: 3fr 2fr;
194 | }
195 | .grid_tablet_40_60 {
196 | grid-template-columns: 2fr 3fr;
197 | }
198 | .grid_tablet_50_25_25 {
199 | grid-template-columns: 2fr 1fr 1fr;
200 | }
201 | .grid_tablet_25_50_25 {
202 | grid-template-columns: 1fr 2fr 1fr;
203 | }
204 | .grid_tablet_25_25_50 {
205 | grid-template-columns: 1fr 1fr 2fr;
206 | }
207 | .grid_tablet_40_30_30 {
208 | grid-template-columns: 4fr 3fr 3fr;
209 | }
210 | .grid_tablet_30_40_30 {
211 | grid-template-columns: 3fr 4fr 3fr;
212 | }
213 | .grid_tablet_30_30_40 {
214 | grid-template-columns: 3fr 3fr 4fr;
215 | }
216 | .grid_tablet_20_40_40 {
217 | grid-template-columns: 1fr 2fr 2fr;
218 | }
219 | .grid_tablet_40_20_40 {
220 | grid-template-columns: 2fr 1fr 2fr;
221 | }
222 | .grid_tablet_40_40_20 {
223 | grid-template-columns: 2fr 2fr 1fr;
224 | }
225 | .gap_tablet_0 {
226 | grid-gap: 0;
227 | }
228 | .gap_tablet_1 {
229 | grid-gap: 1rem;
230 | }
231 | .gap_tablet_2 {
232 | grid-gap: 2rem;
233 | }
234 | .gap_tablet_3 {
235 | grid-gap: 3rem;
236 | }
237 | .gap_tablet_4 {
238 | grid-gap: 4rem;
239 | }
240 | .gap_tablet_5 {
241 | grid-gap: 5rem;
242 | }
243 | .gap_tablet_6 {
244 | grid-gap: 6rem;
245 | }
246 | .gap_tablet_7 {
247 | grid-gap: 7rem;
248 | }
249 | .gap_tablet_8 {
250 | grid-gap: 8rem;
251 | }
252 | .gap_tablet_9 {
253 | grid-gap: 9rem;
254 | }
255 | .gap_tablet_10 {
256 | grid-gap: 10rem;
257 | }
258 | .gap_tablet_11 {
259 | grid-gap: 11rem;
260 | }
261 | .gap_tablet_12 {
262 | grid-gap: 12rem;
263 | }
264 | }
265 |
266 |
267 | @media (min-width: $mq_large) {
268 | .grid_desktop_100 {
269 | grid-template-columns: 1fr;
270 | }
271 | .grid_desktop_50_50 {
272 | grid-template-columns: repeat(2, 1fr);
273 | }
274 | .grid_desktop_50_25_25 {
275 | grid-template-columns: 2fr 1fr 1fr;
276 | }
277 | .grid_desktop_33_33_33 {
278 | grid-template-columns: repeat(3, 1fr);
279 | }
280 | .grid_desktop_75_25 {
281 | grid-template-columns: 3fr 1fr;
282 | }
283 | .grid_desktop_25_75 {
284 | grid-template-columns: 1fr 3fr;
285 | }
286 | .grid_desktop_66_33 {
287 | grid-template-columns: 2fr 1fr;
288 | }
289 | .grid_desktop_60_40 {
290 | grid-template-columns: 3fr 2fr;
291 | }
292 | .grid_desktop_40_60 {
293 | grid-template-columns: 2fr 3fr;
294 | }
295 | .grid_desktop_33_66 {
296 | grid-template-columns: 1fr 2fr;
297 | }
298 | .grid_desktop_50_25_25 {
299 | grid-template-columns: 2fr 1fr 1fr;
300 | }
301 | .grid_desktop_40_30_30 {
302 | grid-template-columns: 4fr 3fr 3fr;
303 | }
304 | .grid_desktop_50_25_25 {
305 | grid-template-columns: 2fr 1fr 1fr;
306 | }
307 | .grid_desktop_25_50_25 {
308 | grid-template-columns: 1fr 2fr 1fr;
309 | }
310 | .grid_desktop_25_25_50 {
311 | grid-template-columns: 1fr 1fr 2fr;
312 | }
313 | .grid_desktop_40_30_30 {
314 | grid-template-columns: 4fr 3fr 3fr;
315 | }
316 | .grid_desktop_30_40_30 {
317 | grid-template-columns: 3fr 4fr 3fr;
318 | }
319 | .grid_desktop_30_30_40 {
320 | grid-template-columns: 3fr 3fr 4fr;
321 | }
322 | .grid_desktop_20_40_40 {
323 | grid-template-columns: 1fr 2fr 2fr;
324 | }
325 | .grid_desktop_40_20_40 {
326 | grid-template-columns: 2fr 1fr 2fr;
327 | }
328 | .grid_desktop_40_40_20 {
329 | grid-template-columns: 2fr 2fr 1fr;
330 | }
331 | .grid_desktop_25_25_25_25 {
332 | grid-template-columns: repeat(4, 1fr);
333 | }
334 | .grid_desktop_40_20_20_20 {
335 | grid-template-columns: 2fr 1fr 1fr 1fr;
336 | }
337 | .grid_desktop_20_40_20_20 {
338 | grid-template-columns: 1fr 2fr 1fr 1fr;
339 | }
340 | .grid_desktop_20_20_40_20 {
341 | grid-template-columns: 1fr 1fr 2fr 1fr;
342 | }
343 | .grid_desktop_20_20_20_40 {
344 | grid-template-columns: 1fr 1fr 1fr 2fr;
345 | }
346 | .grid_desktop_20_20_20_20_20 {
347 | grid-template-columns: repeat(5, 1fr);
348 | }
349 | .grid_desktop_16_16_16_16_16_16 {
350 | grid-template-columns: repeat(6, 1fr);
351 | }
352 |
353 | .gap_desktop_0 {
354 | grid-gap: 0;
355 | }
356 | .gap_desktop_1 {
357 | grid-gap: 1rem;
358 | }
359 | .gap_desktop_2 {
360 | grid-gap: 2rem;
361 | }
362 | .gap_desktop_3 {
363 | grid-gap: 3rem;
364 | }
365 | .gap_desktop_4 {
366 | grid-gap: 4rem;
367 | }
368 | .gap_desktop_5 {
369 | grid-gap: 5rem;
370 | }
371 | .gap_desktop_6 {
372 | grid-gap: 6rem;
373 | }
374 | .gap_desktop_7 {
375 | grid-gap: 7rem;
376 | }
377 | .gap_desktop_8 {
378 | grid-gap: 8rem;
379 | }
380 | .gap_desktop_9 {
381 | grid-gap: 9rem;
382 | }
383 | .gap_desktop_10 {
384 | grid-gap: 10rem;
385 | }
386 | .gap_desktop_11 {
387 | grid-gap: 11rem;
388 | }
389 | .gap_desktop_12 {
390 | grid-gap: 12rem;
391 | }
392 | }
393 |
394 | @media (min-width: $mq_extra) {
395 |
396 | }
397 |
398 |
--------------------------------------------------------------------------------