@@ -362,6 +362,9 @@ $extendOptions: true !default;
362
362
// Custom parser to use for configuration
363
363
$sassConfigParser : null !default ;
364
364
365
+ // Automatically generate CSS from module configuration
366
+ $outputCSSFromConfig : false !default ;
367
+
365
368
// The variable to hold a single module (do not edit)
366
369
$module : null !default ;
367
370
/// Cell Atom - Display property
@@ -479,6 +482,83 @@ $module: null !default;
479
482
480
483
@return $smart-config ;
481
484
}
485
+ /// Used to create a selector from context() arguments
486
+ ///
487
+ /// @param {(string|list)} $block - The name of the module/component that has the context
488
+ /// @param {string} $context - The context you wish to test
489
+ @function create-selector-from-context ($block , $context : null , $pipeContexts : false ) {
490
+ $selector : ();
491
+ $pipedContexts : ' ' ;
492
+ $excludeRootSelector : false;
493
+
494
+ @if $pipeContexts {
495
+ @each $item in $context {
496
+ @if str-index ($item , ' :' ) == 1 {
497
+ $pipedContexts : $pipedContexts + $item ;
498
+ }
499
+ @else {
500
+ $excludeRootSelector : true;
501
+ $pipedContexts : $pipedContexts + ' [class*="#{$modifierGlue }#{$item } "]' ;
502
+ }
503
+ }
504
+ @if type-of ($block ) == ' string' and not $excludeRootSelector {
505
+ $selector : ' .#{$block }#{$pipedContexts } , [class*="#{$block }#{$modifierGlue } "]#{$pipedContexts } ' ;
506
+ }
507
+ @else {
508
+ $selector : ' #{generate-chunk ($block )}#{$pipedContexts } ' ;
509
+ }
510
+ }
511
+
512
+ @else {
513
+ @if $context {
514
+ @each $item in $context {
515
+ @if str-index ($item , ' :' ) == 1 {
516
+ @if type-of ($block ) == ' string' {
517
+ $selector : append ($selector , ' .#{$block }#{$item } ' , comma );
518
+ }
519
+ $selector : append ($selector , ' #{generate-chunk ($block )}#{$item } ' , comma );
520
+ }
521
+ @else {
522
+ $selector : append ($selector , ' #{generate-chunk ($block )} [class*="#{$modifierGlue }#{$item } "]' , comma );
523
+ }
524
+ }
525
+ }
526
+ @else {
527
+ @if type-of ($block ) == ' string' {
528
+ $selector : append ($selector , ' .#{$block } ' , comma );
529
+ $selector : append ($selector , ' [class*="#{$block }#{$modifierGlue } "]' , comma );
530
+ }
531
+ @else {
532
+ $selector : append ($selector , generate-chunk ($block ), comma );
533
+ }
534
+ }
535
+ }
536
+
537
+ @return $selector ;
538
+ }
539
+
540
+ /// Generate a selector chunk from a $block list
541
+ ///
542
+ /// @param {(string|list)} $block
543
+ @function generate-chunk ($block ) {
544
+ $chunk : ' ' ;
545
+
546
+ @if type-of ($block ) == ' list' {
547
+ @for $i from 1 through length ($block ) {
548
+ @if $i == 1 {
549
+ $chunk : $chunk + ' [class*="#{nth ($block , $i )}#{$componentGlue } "]' ;
550
+ }
551
+ @else {
552
+ $chunk : $chunk + ' [class*="#{$componentGlue }#{nth ($block , $i )} "]' ;
553
+ }
554
+ }
555
+ }
556
+ @else {
557
+ $chunk : ' [class*="#{$block }#{$modifierGlue } "]' ;
558
+ }
559
+
560
+ @return $chunk ;
561
+ }
482
562
/// List of known and valid CSS properties
483
563
///
484
564
/// @type Map
@@ -1589,7 +1669,7 @@ $css-properties: (
1589
1669
/// Get CSS from Sass map
1590
1670
///
1591
1671
/// @param {map} $map - The map from which to get CSS
1592
- @mixin get-css-from-map ($map , $sub-component : false) {
1672
+ @mixin get-css-from-map ($map , $sub-component : false, $prevContext : false ) {
1593
1673
@each $property , $value in $map {
1594
1674
@if type-of ($property ) == ' string' {
1595
1675
// $property defines new Modifier
@@ -1613,33 +1693,75 @@ $css-properties: (
1613
1693
}
1614
1694
}
1615
1695
1616
- // $property defines new Modifier
1696
+ // Determine if current node is queried modifier/state
1617
1697
@else if str-index ($property , ' is-' ) == 1 {
1618
1698
@include modifier (str-replace ($property , ' is-' , ' ' )) {
1619
1699
@include get-css-from-map ($value );
1620
1700
}
1621
1701
}
1622
1702
1623
- // $property defines new Modifier on parent element
1624
- @else if str-index ($property , ' -is-' ) {
1625
- $component : str-slice ($property , 1 , str-index ($property , ' -is-' ) - 1 );
1626
- $context : str-slice ($property , str-index ($property , ' -is-' ) + 4 , str-length ($property ));
1703
+ // Determine if parent module/block is queried modifier/state
1704
+ @else if str-index ($property , ' $-is-' ) == 1 or str-index ($property , ' $:' ) == 1 {
1705
+ $context : if (str-index ($property , ' $:' ) == 1 , str-replace ($property , ' $' , ' ' ), str-replace ($property , ' $-is-' , ' ' ));
1627
1706
1628
- @include context (( $module , $component ) , $context ) {
1707
+ @include context ($module , $context ) {
1629
1708
@include get-css-from-map ($value );
1630
1709
}
1631
1710
}
1632
1711
1633
- // $property defines new context
1634
- @else if str-index ($property , ' with-' ) == 1 {
1635
- @include context ($module , str-replace ($property , ' with-' , ' ' )) {
1636
- @include get-css-from-map ($value );
1712
+ // Determine if previously specified parent component is queried modifier/state
1713
+ @else if str-index ($property , ' and-is-' ) == 1 or str-index ($property , ' and:' ) == 1 {
1714
+ $context : if (
1715
+ str-index ($property , ' and-is-' ),
1716
+ str-replace ($property , ' and-is-' , ' ' ),
1717
+ str-slice ($property , str-index ($property , ' :' ), str-length ($property ))
1718
+ );
1719
+ $prevContextVal : (' block' : nth ($prevContext , 1 ), ' context' : nth ($prevContext , 2 ));
1720
+ $prevChunk : create-selector-from-context (map-get ($prevContextVal , ' block' ), map-get ($prevContextVal , ' context' ));
1721
+ $newContextVal : append (map-get ($prevContextVal , ' context' ), $context );
1722
+ $newChunk : create-selector-from-context (map-get ($prevContextVal , ' block' ), $newContextVal , $pipeContexts : true );
1723
+
1724
+ $selector : ();
1725
+
1726
+ @each $chunk in selector-parse (str-replace (inspect ($newChunk ), ' ' , ' , ' )) {
1727
+ @each $item in & {
1728
+ $selector : append ($selector , selector-replace ($item , nth ($prevChunk , 1 ), $chunk ), comma );
1729
+ }
1730
+ }
1731
+
1732
+ @at-root {
1733
+ #{$selector } {
1734
+ @include get-css-from-map ($value , $prevContext : (map-get ($prevContextVal , ' block' ), $newContextVal ));
1735
+ }
1637
1736
}
1638
1737
}
1639
1738
1640
- // $property defines new context
1641
- @else if str-index ($property , ' within-' ) == 1 {
1642
- @include context (str-replace ($property , ' within-' , ' ' )) {
1739
+ // Determine if specified parent component/module is queried modifier/state
1740
+ @else if str-index ($property , ' -is-' ) or (str-index ($property , ' :' ) and str-index ($property , ' :' ) > 1 ) {
1741
+ $component : if (
1742
+ str-index ($property , ' :' ),
1743
+ str-slice ($property , 1 , str-index ($property , ' :' ) - 1 ),
1744
+ str-slice ($property , 1 , str-index ($property , ' -is-' ) - 1 )
1745
+ );
1746
+ $contextVal : if (
1747
+ str-index ($property , ' :' ),
1748
+ str-slice ($property , str-index ($property , ' :' ), str-length ($property )),
1749
+ str-slice ($property , str-index ($property , ' -is-' ) + 4 , str-length ($property ))
1750
+ );
1751
+ $block : if (str-index ($component , ' $' ) == 1 , str-slice ($component , 2 ), $module );
1752
+ $context : if (str-index ($component , ' $' ) == 1 , ($block , $contextVal ), (($block , $component ), $contextVal ));
1753
+
1754
+ @include context ($context ...) {
1755
+ @include get-css-from-map ($value , $prevContext : $context );
1756
+ }
1757
+ }
1758
+
1759
+ // Determine if current node is a child of the queried component/module
1760
+ @else if str-index ($property , ' with-' ) == 1 {
1761
+ $component : str-replace ($property , ' with-' , ' ' );
1762
+ $context : if (str-index ($component , ' $' ) == 1 , str-slice ($component , 2 ), ($module , $component ));
1763
+
1764
+ @include context ($context ) {
1643
1765
@include get-css-from-map ($value );
1644
1766
}
1645
1767
}
@@ -1975,7 +2097,7 @@ $css-properties: (
1975
2097
$disable-output : map-get ($config , ' disable-output' );
1976
2098
}
1977
2099
1978
- // @TODO this needs to identify if nested within itself, not in general
2100
+ // @TODO this needs to identify if nested within itself, not nested in general
1979
2101
$nested : &;
1980
2102
1981
2103
@if not $nested {
@@ -1992,8 +2114,7 @@ $css-properties: (
1992
2114
}
1993
2115
1994
2116
$targetExists : variable-exists (' config' ) and map-has-key ($config , ' target' );
1995
- // @TODO tidy up how $target is used here and in $modifier - also probably
1996
- // won't work for component()
2117
+ // @TODO tidy up how $target is used here and in $modifier - also probably won't work for component()
1997
2118
$target : if ($targetExists , (' module' : $module , ' target' : map-get ($config , ' target' )), false ) !global;
1998
2119
1999
2120
@if not $disable-output {
@@ -2018,7 +2139,7 @@ $css-properties: (
2018
2139
@include extend-modifiers ;
2019
2140
@include combine-modifiers ;
2020
2141
2021
- @if variable-exists (' config' ) {
2142
+ @if variable-exists (' config' ) and $outputCSSFromConfig {
2022
2143
@if $module == map-get ($config , ' name' ) or $target {
2023
2144
@if type-of ($target ) == ' map' and map-get ($target , ' module' ) == $module {
2024
2145
#{map-get ($target , ' target' )} {
@@ -2281,37 +2402,13 @@ $css-properties: (
2281
2402
}
2282
2403
/// Apply styles to a component within a certain context
2283
2404
///
2284
- /// @param {string} $block - The name of the module/component that has the context
2285
- /// @param {string} $context - The context you wish to test
2286
- @mixin context ($block , $context : null) {
2287
- $selector : ();
2288
-
2289
- @if type-of ($block ) == ' list' {
2290
- $block-from-list : false;
2291
- @each $item in $block {
2292
- $block-from-list : if ($block-from-list , ' #{$block-from-list }#{$componentGlue }#{$item } ' , $item );
2293
- }
2294
- $block : $block-from-list ;
2295
- }
2296
-
2297
- @if $context {
2298
- @each $item in $context {
2299
- @if str-index ($item , ' :' ) == 1 {
2300
- $selector : append ($selector , ' .#{$block }#{$item } ' , comma );
2301
- $selector : append ($selector , ' [class*="#{$block }#{$modifierGlue } "]#{$item } ' , comma );
2302
- }
2303
- @else {
2304
- $selector : append ($selector , ' [class*="#{$block }#{$modifierGlue } "][class*="#{$modifierGlue }#{$item } "]' , comma );
2305
- }
2306
- }
2307
- }
2308
- @else {
2309
- $selector : append ($selector , ' .#{$block } ' , comma );
2310
- $selector : append ($selector , ' [class*="#{$block }#{$modifierGlue } "]' , comma );
2311
- }
2405
+ /// @param {arglist} $context
2406
+ @mixin context ($context ...) {
2407
+ $selector : create-selector-from-context ($context ... );
2408
+ $scope : &;
2312
2409
2313
- @each $item in $ selector {
2314
- @at-root #{$item } & {
2410
+ @at-root #{ $ selector} {
2411
+ #{$scope } {
2315
2412
@content ;
2316
2413
}
2317
2414
}
0 commit comments