aboutsummaryrefslogtreecommitdiffstats
path: root/src/bem/_block.scss
diff options
context:
space:
mode:
Diffstat (limited to 'src/bem/_block.scss')
-rw-r--r--src/bem/_block.scss392
1 files changed, 392 insertions, 0 deletions
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 @@
1////
2/// @group BEM
3///
4/// @access public
5////
6
7///
8/// Generate a new block.
9///
10/// This mixin simply creates a new block with the name {namespace}_{name},
11/// where {namespace} is the prefix assigned to $type and {name} is the
12/// block's name.
13///
14/// @param {string} $name - Block name
15/// @param {string} $type [null] - BEMIT namespace of the block
16///
17/// @content
18///
19/// @throw If $type is invalid
20/// @throw If the block is preceded by another block, element, modifier or suffix
21///
22/// @example scss - Creating a new block
23/// @include iro-bem-block('something', 'component') {
24/// /* some definitions */
25/// }
26///
27/// // Generates:
28///
29/// .c-something {
30/// /* some definitions */
31/// }
32///
33@mixin iro-bem-block($name, $type: null) {
34 $result: iro-bem-block($name, $type);
35 $selector: nth($result, 1);
36 $context: nth($result, 2);
37
38 @include iro-bem-validate(
39 'block',
40 (name: $name, type: $type),
41 $selector,
42 $context
43 );
44
45 @if $type != null {
46 $iro-bem-blocks: append($iro-bem-blocks, $name + '_' + $type) !global;
47 } @else {
48 $iro-bem-blocks: append($iro-bem-blocks, $name) !global;
49 }
50
51 @include iro-context-push($iro-bem-context-id, $context...);
52 @at-root #{$selector} {
53 @content;
54 }
55 @include iro-context-pop($iro-bem-context-id);
56}
57
58///
59/// Generate a new block. Check the respective mixin documentation for more information.
60///
61/// @return {list} A list with two items: 1. selector, 2. context or `null`
62///
63/// @see {mixin} iro-bem-block
64///
65@function iro-bem-block($name, $type: null) {
66 //
67 // Possible outcomes:
68 // - ({b,e,m,s}) block
69 //
70
71 $noop: iro-context-assert-stack-count($iro-bem-context-id, $iro-bem-max-depth);
72
73 $selector: null;
74 $base-selector: null;
75
76 @if $type != null {
77 $namespace: map-get($iro-bem-namespaces, $type);
78
79 @if not $namespace {
80 @error '"#{$type}" is not a valid type.';
81 }
82
83 $base-selector: selector-parse('.' + $namespace + '-' + $name);
84
85 @if $type != 'theme' or & {
86 $selector: $base-selector;
87 } @else if not & {
88 $selector: iro-bem-theme-selector($name);
89 }
90 } @else {
91 $base-selector: selector-parse('.' + $name);
92 $selector: $base-selector;
93 }
94
95 @if & {
96 $selector: selector-nest(&, $selector);
97 }
98
99 $context: 'block', (
100 'name': $name,
101 'type': $type,
102 'selector': $selector,
103 'base-selector': $base-selector
104 );
105
106 @return $selector $context;
107}
108
109///
110/// Generate a new object block. It's a shorthand for iro-bem-block($name, 'object').
111///
112/// @param {string} $name - Object block name
113///
114/// @content
115///
116@mixin iro-bem-object($name) {
117 @include iro-bem-block($name, 'object') {
118 @content;
119 }
120}
121
122///
123/// Generate a new object block. Check the respective mixin documentation for more information.
124///
125/// @return {list} A list with two items: 1. selector, 2. context or `null`
126///
127/// @see {mixin} iro-bem-object
128///
129@function iro-bem-object($name) {
130 @return iro-bem-block($name, 'object');
131}
132
133///
134/// Generate a new component block. It's a shorthand for iro-bem-block($name, 'component').
135///
136/// @param {string} $name - Component block name
137///
138/// @content
139///
140@mixin iro-bem-component($name) {
141 @include iro-bem-block($name, 'component') {
142 @content;
143 }
144}
145
146///
147/// Generate a new component block. Check the respective mixin documentation for more information.
148///
149/// @return {list} A list with two items: 1. selector, 2. context or `null`
150///
151/// @see {mixin} iro-bem-component
152///
153@function iro-bem-component($name) {
154 @return iro-bem-block($name, 'component');
155}
156
157///
158/// Generate a new layout block. It's a shorthand for iro-bem-block($name, 'layout').
159///
160/// @param {string} $name - Layout block name
161///
162/// @content
163///
164@mixin iro-bem-layout($name) {
165 @include iro-bem-block($name, 'layout') {
166 @content;
167 }
168}
169
170///
171/// Generate a new layout block. Check the respective mixin documentation for more information.
172///
173/// @return {list} A list with two items: 1. selector, 2. context or `null`
174///
175/// @see {mixin} iro-bem-layout
176///
177@function iro-bem-layout($name) {
178 @return iro-bem-block($name, 'layout');
179}
180
181///
182/// Generate a new utility block. It's a shorthand for iro-bem-block($name, 'utility').
183///
184/// @param {string} $name - Utility block name
185///
186/// @content
187///
188@mixin iro-bem-utility($name) {
189 @include iro-bem-block($name, 'utility') {
190 @content;
191 }
192}
193
194///
195/// Generate a new utility block. Check the respective mixin documentation for more information.
196///
197/// @return {list} A list with two items: 1. selector, 2. context or `null`
198///
199/// @see {mixin} iro-bem-utility
200///
201@function iro-bem-utility($name) {
202 @return iro-bem-block($name, 'utility');
203}
204
205///
206/// Generate a new scope block. It's a shorthand for iro-bem-block($name, 'scope').
207///
208/// @param {string} $name - Scope block name
209///
210/// @content
211///
212@mixin iro-bem-scope($name) {
213 @include iro-bem-block($name, 'scope') {
214 @content;
215 }
216}
217
218///
219/// Generate a new scope block. Check the respective mixin documentation for more information.
220///
221/// @return {list} A list with two items: 1. selector, 2. context or `null`
222///
223/// @see {mixin} iro-bem-scope
224///
225@function iro-bem-scope($name) {
226 @return iro-bem-block($name, 'scope');
227}
228
229///
230/// Generate a new theme block. It's a shorthand for iro-bem-block($name, 'theme').
231///
232/// @param {string} $name - Theme block name
233///
234/// @content
235///
236@mixin iro-bem-theme($name) {
237 @include iro-bem-block($name, 'theme') {
238 @content;
239 }
240}
241
242///
243/// Generate a new theme block. Check the respective mixin documentation for more information.
244///
245/// @return {list} A list with two items: 1. selector, 2. context or `null`
246///
247/// @see {mixin} iro-bem-theme
248///
249@function iro-bem-theme($name) {
250 @return iro-bem-block($name, 'theme');
251}
252
253///
254/// Generate a new JS block. It's a shorthand for iro-bem-block($name, 'js').
255///
256/// @param {string} $name - JS block name
257///
258/// @content
259///
260@mixin iro-bem-js($name) {
261 @include iro-bem-block($name, 'js') {
262 @content;
263 }
264}
265
266///
267/// Generate a new JS block. Check the respective mixin documentation for more information.
268///
269/// @return {list} A list with two items: 1. selector, 2. context or `null`
270///
271/// @see {mixin} iro-bem-js
272///
273@function iro-bem-js($name) {
274 @return iro-bem-block($name, 'js');
275}
276
277///
278/// Generate a new QA block. It's a shorthand for iro-bem-block($name, 'qa').
279///
280/// @param {string} $name - QA block name
281///
282/// @content
283///
284@mixin iro-bem-qa($name) {
285 @include iro-bem-block($name, 'qa') {
286 @content;
287 }
288}
289
290///
291/// Generate a new QA block. Check the respective mixin documentation for more information.
292///
293/// @return {list} A list with two items: 1. selector, 2. context or `null`
294///
295/// @see {mixin} iro-bem-qa
296///
297@function iro-bem-qa($name) {
298 @return iro-bem-block($name, 'qa');
299}
300
301///
302/// Generate a new hack block. It's a shorthand for iro-bem-block($name, 'hack').
303///
304/// @param {string} $name - Hack block name
305///
306/// @content
307///
308@mixin iro-bem-hack($name) {
309 @include iro-bem-block($name, 'hack') {
310 @content;
311 }
312}
313
314///
315/// Generate a new hack block. Check the respective mixin documentation for more information.
316///
317/// @return {list} A list with two items: 1. selector, 2. context or `null`
318///
319/// @see {mixin} iro-bem-hack
320///
321@function iro-bem-hack($name) {
322 @return iro-bem-block($name, 'hack');
323}
324
325///
326/// Assert that a block or element is composed of another block. In BEM, such a relationship is referred to
327/// as a "mix": https://en.bem.info/methodology/key-concepts/#mix
328///
329/// Compilation will fail if the foreign block doesn't exist. This way, you can ensure that blocks are
330/// defined in the right order so that composed blocks/elements will actually override the foreign
331/// declarations without having to artificially increase the specificity.
332///
333/// @param {string | list} $block - Either first block name, or list with two items: 1. block name, 2. block type
334/// @param {string | list} $blocks - Either other block names, or list with two items: 1. block name, 2. block type
335///
336/// @throw If a block type is invalid
337/// @throw If a block doesn't exist
338///
339/// @example scss - Successful assertion
340/// @include iro-bem-component('someBlock') {
341/// /* some definitions */
342/// }
343///
344/// @include iro-bem-component('anotherBlock') {
345/// /* some definitions */
346///
347/// @include iro-bem-element('elem') {
348/// @include iro-bem-composed-of('someBlock' 'component');
349///
350/// /* some definitions */
351/// }
352/// }
353///
354/// // Intended use: <div class="c-anotherBlock__elem c-someBlock">...</div>
355///
356/// @example scss - Failing assertion
357/// @include iro-bem-component('anotherBlock') {
358/// /* some definitions */
359///
360/// @include iro-bem-element('elem') {
361/// @include iro-bem-composed-of('someBlock' 'component');
362///
363/// /* some definitions */
364/// }
365/// }
366///
367/// @include iro-bem-component('someBlock') {
368/// /* some definitions */
369/// }
370///
371/// // Compilation will fail because c-someBlock is defined after c-anotherBlock__elem
372///
373@mixin iro-bem-composed-of($block, $blocks...) {
374 @each $block in iro-list-prepend($blocks, $block) {
375 @if type-of($block) == string {
376 @if not index($iro-bem-blocks, $block) {
377 @error 'Block "#{$block}" does not exist.';
378 }
379 } @else {
380 $name: nth($block, 1);
381 $type: nth($block, 2);
382
383 @if not map-get($iro-bem-namespaces, $type) {
384 @error '"#{$type}" is not a valid type.';
385 }
386
387 @if not index($iro-bem-blocks, $name + '_' + $type) {
388 @error 'Block "#{$name}" does not exist.';
389 }
390 }
391 }
392}