/* stylelint-disable max-nesting-depth */
/*
@render-pseudoclass
Build a pseucoclass utiliy from values calculated in the @render-utilities-in loop
*/
@mixin render-pseudoclass(
$utility, $pseudoclass, $selector, $property, $value, $media-prefix
) {
$important: if($utilities-use-important, " !important", null); $this-mq: null; .#{$media-prefix}#{$pseudoclass}\:#{ns("utility")}#{$selector}:#{$pseudoclass} { @each $this-property in $property { #{$this-property}: unquote("#{$value}#{$important}"); } }
}
// utility-feature? utility-property @mixin add-utility-declaration($declaration, $utility-type, $important) {
@each $ext-prop, $ext-value in map-get($declaration, $utility-type) { #{strunquote($ext-prop)}: unquote("#{strunquote($ext-value)}#{$important}"); }
}
/*
@render-utility
Build a utility from values calculated in the @render-utilities-in loop
TODO: Determine the proper use of unquote() in the following. Changed to account for a 'interpolation near operators will be simplified in a future version of Sass' warning.
*/
@mixin render-utility(
$utility, $selector, $property, $value, $val-props, $media-key
) {
$important: if($utilities-use-important, " !important", null); $media-prefix: null; $value-is-map: if(type-of($val-props) == "map", true, false); @if $media-key { $media-prefix: #{$media-key}\:; } .#{$media-prefix}#{ns("utility")}#{$selector} { @if $value-is-map and map-has-key($val-props, extend) { @include add-utility-declaration($val-props, extend, $important); } @if $value-is-map and map-has-key($val-props, extends) { @extend %#{map-get($val-props, extends)}; } @each $this-property in $property { #{$this-property}: unquote("#{$value}#{$important}"); } @if map-has-key($utility, extend) { @include add-utility-declaration($utility, extend, $important); } } // Add the pseudoclass variants, if applicable @if map-deep-get($utility, settings, hover) { @include render-pseudoclass( $utility, hover, $selector, $property, $value, $media-prefix ); } @if map-deep-get($utility, settings, active) { @include render-pseudoclass( $utility, active, $selector, $property, $value, $media-prefix ); } @if map-deep-get($utility, settings, visited) { @include render-pseudoclass( $utility, visited, $selector, $property, $value, $media-prefix ); } @if map-deep-get($utility, settings, focus) { @include render-pseudoclass( $utility, focus, $selector, $property, $value, $media-prefix ); } // And add the responsive prefixes, if applicable /* @if map-deep-get($utility, settings, responsive) { @include render-media-queries( $utility, $selector, $property, $value, $val-props ); } */
}
/*
@render-utilities-in
The master loop that sets the building blocks of utilities from the values in individual rule settings and loops through all possible variants
*/
@mixin these-utilities($utilities, $media-key: false) {
// loop through the $utilities @each $utility-name, $utility in $utilities { // Only do this if the the utility is meant to output @if not($media-key) or ($media-key and map-deep-get($utility, settings, responsive)) { @if map-deep-get($utility, settings, output) or $output-all-utilities { // set intital variants // $property-default is a single value for all these utilities $base-props: null; $modifier: null; $selector: null; $property-default: map-get($utility, property); $property: null; $value: null; $our-modifiers: (); $b: null; $v: null; $mv: null; $val-props: (); $no-value: false; $b: map-get($utility, base); // Each utility rule takes a value, so let's start here // and begin building. // -------- For each value in utility.values ---------- @each $val-key, $val-value in map-get($utility, values) { // If $val-value == null, or if $val-value is a map and // the content key or the dependency key has a null value // set $val-value to `false`... @if type-of($val-value) == "map" { @if not map-get($val-value, content) { $val-value: false; } @else if map-has-key($val-value, dependency) and not map-get($val-value, dependency) { $val-value: false; } } // ...so we can skip building this rule altogether. // So, if $val-value is _not_ false... @if $val-value { // Set the value of our rule. // If its a map, use val-value.content. $val-slug: if( type-of($val-value) == "map", map-get($val-value, "slug"), $val-key ); $value: if( type-of($val-value) == "map", map-get($val-value, "content"), $val-value ); @if $val-slug == "" or smart-quote($val-slug) == "noValue" { $no-value: true; } // Add any appended values... @if map-get($utility, valueAppend) { $value: $value + map-get($utility, valueAppend); } // ...or prepended values. @if map-get($utility, valuePrepend) { $value: map-get($utility, valuePrepend) + $value; } // Then unquote the entire value string. $value: strunquote($value); // And we'll set the $v as $val-slug for use in // constructing the selector (.$b-$m-$v). $v: $val-slug; // -------- Start of Modifiers ---------- // Now we'll check for modifiers and loop through them // to get the props we need to build our rule. // Modifiers are held in a MAP, // where each individual modifer has the keypair // [slug]:[value] // So, check for modifiers. @if map-get($utility, modifiers) != null { // If there are modifiers, capture them as $our-modifiers. $our-modifiers: map-get($utility, modifiers); } @else { // If there aren't, build a dummy so we can keep // all our build in the same loop. $our-modifiers: ( "slug": null, ); } // OK! C'mon, let's loop! // https://www.youtube.com/watch?v=X9i2i07wPUw // -------- For each modifier in $our-modifiers ---------- @each $mod-key, $mod-val in $our-modifiers { $property: if( $mod-val == null or $mod-val == "", $property-default, multi-cat($property-default, $mod-val) ); // Now we go through to set the $selector. // If mod-props.slug is noModifier... @if $mod-key == "" or $mod-key == slug or smart-quote($mod-key) == "noModifier" { // First, we can test to see if the base $b is null @if $b == null { // If it _is_ null, the rule's selector is $v. $selector: $v; // if the value is noValue ('') } @else if $no-value { // selector is the base only $selector: $b; } @else { // otherwise, selctor is joined with a hyphen. $selector: $b + "-" + $v; // Nice! We just took care of the non-modifier cases! } } // If there _is_ a modifier... @else { $mv: if($no-value, $mod-key, $mod-key + "-" + $v); // Once we have $mv, test for $b // and build the selector as before. $selector: if($b == null, $mv, $b + "-" + $mv); } // finished setting modifier vars // Hey. Did we just finish $selector? // And do we also have $property and $value? // We do?!?!?! We do! // FINALLY, 'BUILD THE RULE, MAX!' // https://www.youtube.com/watch?v=R3Igz5SfBCE @include render-utility( $utility, $selector, $property, $value, $val-value, $media-key ); } // end the modifier loop } // end the null value conditional } // end the value loop } // end the output conditional } } // end the utility loop // (ノ◕ヮ◕)ノ*:・゚✧
}
@mixin render-utilities-in($utilities) {
@include these-utilities($utilities); $our-breakpoints: map-deep-get($system-properties, breakpoints, standard); @each $media-key, $media-value in $our-breakpoints { @if map-get($theme-utility-breakpoints, $media-key) { @include at-media($media-key) { @include these-utilities($utilities, $media-key); } } }
}
/* stylelint-enable */