diff options
author | Feuerfuchs <git@feuerfuchs.dev> | 2020-11-01 20:55:14 +0100 |
---|---|---|
committer | Feuerfuchs <git@feuerfuchs.dev> | 2020-11-01 20:55:14 +0100 |
commit | d07f664450ddaaebb44127a4bd057763d13d3f82 (patch) | |
tree | 234cfd673ac527869a8dda4f32afbec48c87b512 /src/bem/_block.scss | |
download | iro-sass-d07f664450ddaaebb44127a4bd057763d13d3f82.tar.gz iro-sass-d07f664450ddaaebb44127a4bd057763d13d3f82.tar.bz2 iro-sass-d07f664450ddaaebb44127a4bd057763d13d3f82.zip |
Init
Diffstat (limited to 'src/bem/_block.scss')
-rw-r--r-- | src/bem/_block.scss | 392 |
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 | } | ||