From d07f664450ddaaebb44127a4bd057763d13d3f82 Mon Sep 17 00:00:00 2001 From: Feuerfuchs Date: Sun, 1 Nov 2020 20:55:14 +0100 Subject: Init --- src/bem/_block.scss | 392 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 src/bem/_block.scss (limited to 'src/bem/_block.scss') diff --git a/src/bem/_block.scss b/src/bem/_block.scss new file mode 100644 index 0000000..d065891 --- /dev/null +++ b/src/bem/_block.scss @@ -0,0 +1,392 @@ +//// +/// @group BEM +/// +/// @access public +//// + +/// +/// Generate a new block. +/// +/// This mixin simply creates a new block with the name {namespace}_{name}, +/// where {namespace} is the prefix assigned to $type and {name} is the +/// block's name. +/// +/// @param {string} $name - Block name +/// @param {string} $type [null] - BEMIT namespace of the block +/// +/// @content +/// +/// @throw If $type is invalid +/// @throw If the block is preceded by another block, element, modifier or suffix +/// +/// @example scss - Creating a new block +/// @include iro-bem-block('something', 'component') { +/// /* some definitions */ +/// } +/// +/// // Generates: +/// +/// .c-something { +/// /* some definitions */ +/// } +/// +@mixin iro-bem-block($name, $type: null) { + $result: iro-bem-block($name, $type); + $selector: nth($result, 1); + $context: nth($result, 2); + + @include iro-bem-validate( + 'block', + (name: $name, type: $type), + $selector, + $context + ); + + @if $type != null { + $iro-bem-blocks: append($iro-bem-blocks, $name + '_' + $type) !global; + } @else { + $iro-bem-blocks: append($iro-bem-blocks, $name) !global; + } + + @include iro-context-push($iro-bem-context-id, $context...); + @at-root #{$selector} { + @content; + } + @include iro-context-pop($iro-bem-context-id); +} + +/// +/// Generate a new block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-block +/// +@function iro-bem-block($name, $type: null) { + // + // Possible outcomes: + // - ({b,e,m,s}) block + // + + $noop: iro-context-assert-stack-count($iro-bem-context-id, $iro-bem-max-depth); + + $selector: null; + $base-selector: null; + + @if $type != null { + $namespace: map-get($iro-bem-namespaces, $type); + + @if not $namespace { + @error '"#{$type}" is not a valid type.'; + } + + $base-selector: selector-parse('.' + $namespace + '-' + $name); + + @if $type != 'theme' or & { + $selector: $base-selector; + } @else if not & { + $selector: iro-bem-theme-selector($name); + } + } @else { + $base-selector: selector-parse('.' + $name); + $selector: $base-selector; + } + + @if & { + $selector: selector-nest(&, $selector); + } + + $context: 'block', ( + 'name': $name, + 'type': $type, + 'selector': $selector, + 'base-selector': $base-selector + ); + + @return $selector $context; +} + +/// +/// Generate a new object block. It's a shorthand for iro-bem-block($name, 'object'). +/// +/// @param {string} $name - Object block name +/// +/// @content +/// +@mixin iro-bem-object($name) { + @include iro-bem-block($name, 'object') { + @content; + } +} + +/// +/// Generate a new object block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-object +/// +@function iro-bem-object($name) { + @return iro-bem-block($name, 'object'); +} + +/// +/// Generate a new component block. It's a shorthand for iro-bem-block($name, 'component'). +/// +/// @param {string} $name - Component block name +/// +/// @content +/// +@mixin iro-bem-component($name) { + @include iro-bem-block($name, 'component') { + @content; + } +} + +/// +/// Generate a new component block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-component +/// +@function iro-bem-component($name) { + @return iro-bem-block($name, 'component'); +} + +/// +/// Generate a new layout block. It's a shorthand for iro-bem-block($name, 'layout'). +/// +/// @param {string} $name - Layout block name +/// +/// @content +/// +@mixin iro-bem-layout($name) { + @include iro-bem-block($name, 'layout') { + @content; + } +} + +/// +/// Generate a new layout block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-layout +/// +@function iro-bem-layout($name) { + @return iro-bem-block($name, 'layout'); +} + +/// +/// Generate a new utility block. It's a shorthand for iro-bem-block($name, 'utility'). +/// +/// @param {string} $name - Utility block name +/// +/// @content +/// +@mixin iro-bem-utility($name) { + @include iro-bem-block($name, 'utility') { + @content; + } +} + +/// +/// Generate a new utility block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-utility +/// +@function iro-bem-utility($name) { + @return iro-bem-block($name, 'utility'); +} + +/// +/// Generate a new scope block. It's a shorthand for iro-bem-block($name, 'scope'). +/// +/// @param {string} $name - Scope block name +/// +/// @content +/// +@mixin iro-bem-scope($name) { + @include iro-bem-block($name, 'scope') { + @content; + } +} + +/// +/// Generate a new scope block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-scope +/// +@function iro-bem-scope($name) { + @return iro-bem-block($name, 'scope'); +} + +/// +/// Generate a new theme block. It's a shorthand for iro-bem-block($name, 'theme'). +/// +/// @param {string} $name - Theme block name +/// +/// @content +/// +@mixin iro-bem-theme($name) { + @include iro-bem-block($name, 'theme') { + @content; + } +} + +/// +/// Generate a new theme block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-theme +/// +@function iro-bem-theme($name) { + @return iro-bem-block($name, 'theme'); +} + +/// +/// Generate a new JS block. It's a shorthand for iro-bem-block($name, 'js'). +/// +/// @param {string} $name - JS block name +/// +/// @content +/// +@mixin iro-bem-js($name) { + @include iro-bem-block($name, 'js') { + @content; + } +} + +/// +/// Generate a new JS block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-js +/// +@function iro-bem-js($name) { + @return iro-bem-block($name, 'js'); +} + +/// +/// Generate a new QA block. It's a shorthand for iro-bem-block($name, 'qa'). +/// +/// @param {string} $name - QA block name +/// +/// @content +/// +@mixin iro-bem-qa($name) { + @include iro-bem-block($name, 'qa') { + @content; + } +} + +/// +/// Generate a new QA block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-qa +/// +@function iro-bem-qa($name) { + @return iro-bem-block($name, 'qa'); +} + +/// +/// Generate a new hack block. It's a shorthand for iro-bem-block($name, 'hack'). +/// +/// @param {string} $name - Hack block name +/// +/// @content +/// +@mixin iro-bem-hack($name) { + @include iro-bem-block($name, 'hack') { + @content; + } +} + +/// +/// Generate a new hack block. Check the respective mixin documentation for more information. +/// +/// @return {list} A list with two items: 1. selector, 2. context or `null` +/// +/// @see {mixin} iro-bem-hack +/// +@function iro-bem-hack($name) { + @return iro-bem-block($name, 'hack'); +} + +/// +/// Assert that a block or element is composed of another block. In BEM, such a relationship is referred to +/// as a "mix": https://en.bem.info/methodology/key-concepts/#mix +/// +/// Compilation will fail if the foreign block doesn't exist. This way, you can ensure that blocks are +/// defined in the right order so that composed blocks/elements will actually override the foreign +/// declarations without having to artificially increase the specificity. +/// +/// @param {string | list} $block - Either first block name, or list with two items: 1. block name, 2. block type +/// @param {string | list} $blocks - Either other block names, or list with two items: 1. block name, 2. block type +/// +/// @throw If a block type is invalid +/// @throw If a block doesn't exist +/// +/// @example scss - Successful assertion +/// @include iro-bem-component('someBlock') { +/// /* some definitions */ +/// } +/// +/// @include iro-bem-component('anotherBlock') { +/// /* some definitions */ +/// +/// @include iro-bem-element('elem') { +/// @include iro-bem-composed-of('someBlock' 'component'); +/// +/// /* some definitions */ +/// } +/// } +/// +/// // Intended use:
...
+/// +/// @example scss - Failing assertion +/// @include iro-bem-component('anotherBlock') { +/// /* some definitions */ +/// +/// @include iro-bem-element('elem') { +/// @include iro-bem-composed-of('someBlock' 'component'); +/// +/// /* some definitions */ +/// } +/// } +/// +/// @include iro-bem-component('someBlock') { +/// /* some definitions */ +/// } +/// +/// // Compilation will fail because c-someBlock is defined after c-anotherBlock__elem +/// +@mixin iro-bem-composed-of($block, $blocks...) { + @each $block in iro-list-prepend($blocks, $block) { + @if type-of($block) == string { + @if not index($iro-bem-blocks, $block) { + @error 'Block "#{$block}" does not exist.'; + } + } @else { + $name: nth($block, 1); + $type: nth($block, 2); + + @if not map-get($iro-bem-namespaces, $type) { + @error '"#{$type}" is not a valid type.'; + } + + @if not index($iro-bem-blocks, $name + '_' + $type) { + @error 'Block "#{$name}" does not exist.'; + } + } + } +} -- cgit v1.2.3-70-g09d2