@use "sass:map"; @use "../config" as *; @use "../vendor/rfs" as *; // stylelint-disable scss/dollar-variable-pattern // Utility generator // - Utilities can four different types of selectors: // - class: .class // - attr-starts: [class^="class"] // - attr-includes: [class*="class"] // - any other string: used directly as a custom selector (e.g., "& > :not(:last-child)") // - Utilities can generate a regular CSS property or a CSS custom property // - Utilities can be responsive or not // - Utilities can have a state (e.g., :hover, :focus, :active, etc.) @mixin generate-utility($utility, $infix: "", $is-rfs-media-query: false) { // Determine if we're generating a class, or an attribute selector, or using a custom selector $selectorType: if(map.has-key($utility, selector), map.get($utility, selector), "class"); // Then get the class name to use in a class (e.g., .class) or in a attribute selector (e.g., [class^="class"]) $selectorClass: map.get($utility, class); // Get the list or map of values and ensure it's a map $values: map.get($utility, values); @if type-of($values) != "map" { @if type-of($values) == "list" { $list: (); @each $value in $values { $list: map.merge($list, ($value: $value)); } $values: $list; } @else { $values: (null: $values); } } // Calculate infix once, before the loop $infix: if($infix == "", "", "-" + $infix); @each $key, $value in $values { $properties: map.get($utility, property); // Multiple properties are possible, for example with vertical or horizontal margins or paddings @if type-of($properties) == "string" { $properties: append((), $properties); } // Use custom class if present, otherwise use the first value from the list of properties $customClass: if(map.has-key($utility, class), map.get($utility, class), nth($properties, 1)); $customClass: if($customClass == null, "", $customClass); // Use custom CSS variable name if present, otherwise default to `class` // mdo-do: restore? // $css-variable-name: if(map.has-key($utility, css-variable-name), map.get($utility, css-variable-name), map.get($utility, class)); // State params to generate pseudo-classes $state: if(map.has-key($utility, state), map.get($utility, state), ()); // $infix: if($customClass == "" and str-slice($infix, 1, 1) == "-", str-slice($infix, 2), $infix); // Don't prefix if value key is null (e.g. with shadow class) $customClassModifier: if($key, if($customClass == "" and $infix == "", "", "-") + $key, ""); $selector: ""; @if $selectorType == "class" { // Use the fallback of the first property if no `class` key is used @if $customClass != "" { $selector: ".#{$customClass + $infix + $customClassModifier}"; } @else { $selector: ".#{$selectorClass + $infix + $customClassModifier}"; } } @else if $selectorType == "attr-starts" { $selector: "[class^=\"#{$selectorClass}\"]"; } @else if $selectorType == "attr-includes" { $selector: "[class*=\"#{$selectorClass}\"]"; } @else { // Use the selector value directly as a custom selector string $selector: $selectorType; } // @debug $utility; // @debug $selectorType; // @debug $selector; // @debug $properties; // @debug $values; #{$selector} { @if map.get($utility, rfs) { @if $is-rfs-media-query { @each $property in $properties { @include rfs($value, $property); } } @else { @each $property in $properties { @include rfs($value, $property); } } } @else { @each $property in $properties { #{$property}: $value; } } } // @if $value != null { // #{$selector} { // @each $property in $properties { // #{$property}: $value; // } // } // @if $is-css-var { // #{$selector} { // --#{$prefix}#{$css-variable-name}: #{$value}; // } // @each $pseudo in $state { // #{$selector}-#{$pseudo}:#{$pseudo} { // --#{$prefix}#{$css-variable-name}: #{$value}; // } // } // } @else { // #{$selector} { // @each $property in $properties { // // @if $is-local-vars { // // @each $local-var, $variable in $is-local-vars { // // --#{$prefix}#{$local-var}: #{$variable}; // // } // // } // #{$property}: $value; // } // } // // @each $pseudo in $state { // // #{$selector}-#{$pseudo}:#{$pseudo} { // // @each $property in $properties { // // @if $is-local-vars { // // @each $local-var, $variable in $is-local-vars { // // --#{$prefix}#{$local-var}: #{$variable}; // // } // // } // // #{$property}: $value; // // } // // } // // } // } // } $is-css-var: map.get($utility, css-var); $is-local-vars: map.get($utility, local-vars); // $is-rtl: map.get($utility, rtl); } }