Skip to content

Commit

Permalink
custom css attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
markhuot committed Oct 31, 2023
1 parent ab94dd9 commit 660da02
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 85 deletions.
29 changes: 29 additions & 0 deletions src/attributes/Custom.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace markhuot\keystone\attributes;

use Illuminate\Support\Collection;
use markhuot\keystone\base\Attribute;

class Custom extends Attribute
{
public function __construct(
protected ?string $value = ''
) {
}

public function getInputHtml(): string
{
return \Craft::$app->getView()->renderTemplate('keystone/attributes/custom', [
'name' => get_class($this),
'value' => $this->value,
]);
}

public function toAttributeArray(): array
{
$className = \Craft::$app->getView()->registerCssRule($this->value);

return ['class' => $className];
}
}
2 changes: 1 addition & 1 deletion src/attributes/SpaceBetween.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function toAttributeArray(): array
'x' => ['margin-left' => $value],
'y' => ['margin-top' => $value],
})
->map(fn ($value, $key) => \Craft::$app->getView()->registerCssRule($value, $key, '& > * + *'));
->map(fn ($value, $key) => \Craft::$app->getView()->registerCssDeclaration($value, $key, '& > * + *'));

return array_filter(['class' => $classNames->join(' ')]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/base/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ abstract public function getInputHtml(): string;
public function toAttributeArray(): array
{
$classNames = $this->getCssRules()
->map(\Craft::$app->getView()->registerCssRule(...));
->map(\Craft::$app->getView()->registerCssDeclaration(...));

return ['class' => $classNames->join(' ')];
}
Expand Down
51 changes: 51 additions & 0 deletions src/base/CssRuleBag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace markhuot\keystone\base;

use yii\helpers\Html;

class CssRuleBag
{
protected array $rules = [];

public function addDeclaration($value, $key, $selector = null)
{
return $this->addRule($key.':'.$value, $selector);
}

public function addRule(string $rule, ?string $selector = null)
{
$hash = hash('sha1', $rule.$selector);

if (isset($this->rules[$hash])) {
return 'c'.array_search($hash, array_keys($this->rules));
}
else {
$this->rules[$hash] = [
'rule' => $rule,
'selector' => $selector,
];

return 'c'.(count($this->rules) - 1);
}
}

public function getRules()
{
return $this->rules;
}

public function __toString()
{
return Html::style(collect($this->rules)
->values()
->map(function ($rule, $index) {
$class = ".c{$index}";
$selector = $rule['selector'] ?? '&';
$selector = str_replace('&', $class, $selector);

return "{$selector}{{$rule['rule']}}";
})
->join("\n"));
}
}
52 changes: 12 additions & 40 deletions src/behaviors/CssRuleBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace markhuot\keystone\behaviors;

use craft\web\View;
use markhuot\keystone\base\CssRuleBag;
use yii\base\Behavior;
use yii\helpers\Html;

Expand All @@ -11,49 +12,18 @@
*/
class CssRuleBehavior extends Behavior
{
public function registerCssRule(string $value, string $key, string $selector = null)
public function registerCssRule(string $rule, string $selector = null)
{
$this->owner->css['__cssRules'] ??= new class
{
protected array $rules = [];
$this->owner->css['__cssRules'] ??= new CssRuleBag;

public function addRule($value, $key, $selector = null)
{
$hash = hash('sha1', $value.$key.$selector);
if (isset($this->rules[$hash])) {
return 'c'.array_search($hash, array_keys($this->rules));
} else {
$this->rules[$hash] = [
'property' => $key,
'value' => $value,
'selector' => $selector,
];

return 'c'.(count($this->rules) - 1);
}
}

public function getRules()
{
return $this->rules;
}

public function __toString()
{
return Html::style(collect($this->rules)
->values()
->map(function ($rule, $index) {
$class = ".c{$index}";
$selector = $rule['selector'] ?? '&';
$selector = str_replace('&', $class, $selector);
return $this->owner->css['__cssRules']->addRule($rule, $selector);
}

return "{$selector}{{$rule['property']}:{$rule['value']}}";
})
->join("\n"));
}
};
public function registerCssDeclaration(string $value, string $key, string $selector = null)
{
$this->owner->css['__cssRules'] ??= new CssRuleBag;

return $this->owner->css['__cssRules']->addRule($value, $key, $selector);
return $this->owner->css['__cssRules']->addDeclaration($value, $key, $selector);
}

public function clearCssRules()
Expand All @@ -65,6 +35,8 @@ public function clearCssRules()

public function getCssRules()
{
return $this->owner->css['__cssRules']?->getRules() ?? null;
$this->owner->css['__cssRules'] ??= new CssRuleBag;

return $this->owner->css['__cssRules']->getRules() ?? null;
}
}
1 change: 1 addition & 0 deletions src/listeners/RegisterDefaultAttributeTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public function handle(RegisterAttributeType $event): void
$event->add(\markhuot\keystone\attributes\Alignment::class);
$event->add(\markhuot\keystone\attributes\Background::class);
$event->add(\markhuot\keystone\attributes\Border::class);
$event->add(\markhuot\keystone\attributes\Custom::class);
$event->add(\markhuot\keystone\attributes\Display::class);
$event->add(\markhuot\keystone\attributes\Grid::class);
$event->add(\markhuot\keystone\attributes\Margin::class);
Expand Down
59 changes: 35 additions & 24 deletions src/resources/keystone.min.css
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,11 @@ video {
margin: 0px !important;
}

.k-mx-auto {
margin-left: auto;
margin-right: auto;
}

.k-ml-\[2rem\] {
margin-left: 2rem;
}
Expand All @@ -582,6 +587,18 @@ video {
margin-right: 0.5rem;
}

.\!k-mt-0 {
margin-top: 0px !important;
}

.k-mt-6 {
margin-top: 1.5rem;
}

.k-mb-6 {
margin-bottom: 1.5rem;
}

.k-block {
display: block;
}
Expand Down Expand Up @@ -626,6 +643,10 @@ video {
width: 100%;
}

.k-w-auto {
width: auto;
}

.k-flex-grow {
flex-grow: 1;
}
Expand All @@ -635,6 +656,12 @@ video {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.k-select-none {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}

.k-grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
Expand All @@ -643,6 +670,14 @@ video {
grid-template-columns: repeat(3, minmax(0, 1fr));
}

.k-items-end {
align-items: flex-end;
}

.k-justify-center {
justify-content: center;
}

.k-justify-between {
justify-content: space-between;
}
Expand Down Expand Up @@ -884,30 +919,6 @@ video {
opacity: 0.25;
}

.\[\&\:has\(li\)\]\:k-block:has(li) {
display: block;
}

.\[\&\:has\(li\:not\(\.disabled\)\)\]\:k-block:has(li:not(.disabled)) {
display: block;
}

.\[\&\:has\(li\:not\(\.k-hidden\)\)\]\:k-block:has(li:not(.k-hidden)) {
display: block;
}

.\[\&\:has\(ul\)\]\:k-block:has(ul) {
display: block;
}

.\[\&\:has\(ul\>li\:not\(\.k-hidden\)\)\]\:k-block:has(ul>li:not(.k-hidden)) {
display: block;
}

.\[\&\:has\(ul_li\:not\(\.k-hidden\)\)\]\:k-block:has(ul li:not(.k-hidden)) {
display: block;
}

.\[\&\:has\(ul_ul\>li\:not\(\.k-hidden\)\)\]\:k-block:has(ul ul>li:not(.k-hidden)) {
display: block;
}
7 changes: 7 additions & 0 deletions src/templates/attributes/custom.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% from '_includes/forms' import textareaField %}

{{ textareaField({
'label': 'Custom CSS',
'name': name,
'value': value|default,
}) }}
22 changes: 15 additions & 7 deletions src/templates/attributes/grid.twig
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
{% from '_includes/forms' import textField %}

{{ textField({
'label': 'Columns',
'name': name ~ '[grid-template-columns]',
'type': 'number',
'value': value['grid-template-columns']|default,
'fieldClass': '!k-m-0',
}) }}
<div class="k-space-y-6">
{{ textField({
'label': 'Columns',
'name': name ~ '[grid-template-columns]',
'type': 'number',
'value': value['grid-template-columns']|default,
}) }}

{{ textField({
'label': 'Gap',
'name': name ~ '[grid-gap]',
'type': 'text',
'value': value['grid-gap']|default,
}) }}
</div>
18 changes: 9 additions & 9 deletions src/templates/attributes/text.twig
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@
name: name ~ '[font-weight]',
options: [
{label: 'Default', value: ''},
{label: '100', value: '100'},
{label: '200', value: '200'},
{label: '300', value: '300'},
{label: '400', value: '400'},
{label: '500', value: '500'},
{label: '600', value: '600'},
{label: '700', value: '700'},
{label: '800', value: '800'},
{label: '900', value: '900'},
{label: '100 Thin', value: '100'},
{label: '200 Extra light', value: '200'},
{label: '300 Light', value: '300'},
{label: '400 Normal', value: '400'},
{label: '500 Medium', value: '500'},
{label: '600 Semi bold', value: '600'},
{label: '700 Bold', value: '700'},
{label: '800 Extra bold', value: '800'},
{label: '900 Black', value: '900'},
],
value: value['font-weight']|default('400')
}) }}
Expand Down
4 changes: 2 additions & 2 deletions src/templates/components/heading.twig
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
{% export category = "Text" %}
{% export icon %}<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M150,56V176a6,6,0,0,1-12,0V122H46v54a6,6,0,0,1-12,0V56a6,6,0,0,1,12,0v54h92V56a6,6,0,0,1,12,0Zm90,146H204L240,154.05A30,30,0,1,0,187.71,126,6,6,0,1,0,199,130a18,18,0,0,1,14.47-11.82,18,18,0,0,1,16.87,28.66L187.2,204.4A6,6,0,0,0,192,214h48a6,6,0,0,0,0-12Z"></path></svg>{% endexport %}
{% set level = props.level.value|default(1) %}
{% set fontSize = craft.app.getView().registerCssRule((32 - (level-1)*4) ~ 'px', 'font-size') %}
{% set fontWeight = craft.app.getView().registerCssRule('bold', 'font-weight') %}
{% set fontSize = craft.app.getView().registerCssDeclaration((32 - (level-1)*4) ~ 'px', 'font-size') %}
{% set fontWeight = craft.app.getView().registerCssDeclaration('bold', 'font-weight') %}
<h{{ level }} {{ attributes.merge({class: [fontSize, fontWeight]|join(' ')}) }}>
{% slot %}{% endslot %}
</h{{ level }}>
18 changes: 18 additions & 0 deletions src/templates/edit/design.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% from '_includes/forms' import field as selectizeField %}

{% macro hiddenInputs(name, value) %}
{% if value|is_iterable %}
{% for k,v in value %}
Expand All @@ -8,8 +9,25 @@
{{ hiddenInput(name, value) }}
{% endif %}
{% endmacro %}

{% set attributeTypes = create('markhuot\\keystone\\actions\\GetAttributeTypes').handle() %}

<div id="tab-design" class="{{ component.getType().getFieldDefinitions().isNotEmpty() ? 'hidden' }} k-pt-xl k-field-reset" x-data='{}' @input.debounce.1000ms='post("keystone/components/update").then(() => Craft.Preview.instances[0] && Craft.Preview.instances[0].updateIframe())'>
<div class="k-mb-6">
<p>Update the component design under various states.</p>
<div class="btngroup">
<label class="btn [&:has(:checked)]:k-bg-ui-control-active" tabindex="0">
<input type="radio" name="design-pseudo" value="" checked class="k-hidden">
default
</label>
<label class="btn [&:has(:checked)]:k-bg-ui-control-active" tabindex="0">
<input type="radio" name="design-pseudo" value="start" class="k-hidden">
hover
</label>
</div>
</div>
<hr>

{% namespace 'fields[_attributes]' %}
{% for type, value in component.data._attributes %}
<div class="k-relative">
Expand Down
2 changes: 1 addition & 1 deletion src/templates/select.twig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
document.querySelector('li:not(.k-hidden) input[type=radio][name^={{ craft.app.getView().getNamespace }}]').checked = true;
">
</div>
<ul class="k-space-y-8">
<ul class="k-space-y-8 k-select-none">
{% for category, types in groups %}
<li class="k-hidden [&:has(ul_li:not(.k-hidden))]:k-block">
<p class="k-font-bold k-text-gray-400">{{ category }}</p>
Expand Down

0 comments on commit 660da02

Please sign in to comment.