aboutsummaryrefslogtreecommitdiffstats
path: root/src/sass/lib/css-vars.scss
blob: cb25183168fae6c09366a69103f5a06acfc108a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Downloaded from https://github.com/malyw/css-vars

//// VARIABLES ////

// global map to be filled via variables
$css-vars: ();

// the variable may be set to "true" anywhere in the code,
// so native CSS custom properties will be used instead of the Sass global map
$css-vars-use-native: false !default;

// enables the output of debug messages
$css-vars-debug-log: false !default;

//// FUNCTIONS ////

///
// Assigns a variable to the global map
///
@function _cssVarAssign($varName: null, $varValue: null) {
    // CHECK PARAMS
    @if ($varName==null) {
        @error 'Variable name is expected, instead got: null';
    }
    @if ($varValue==null) {
        @error 'Variable value is expected, instead got: null';
    }

    // assign to the global map
    @if ($css-vars-debug-log and map-get($css-vars, $varName)) {
        @debug "'#{$varName}' variable is reassigned";
    }

    @return map-merge($css-vars, ($varName: $varValue));
}

///
// Emulates var() CSS native function behavior
//
// $args[0] {String} "--" + variable name
// [$args[1]] Optional default value if variable is not assigned yet
//
// E.G.:
// color: var(--main-color);
// background: var(--main-bg, green);
///
@function var($args...) {
    // CHECK PARAMS
    @if (length($args) ==0) {
        @error 'Variable name is expected to be passed to the var() function';
    }
    @if (str-length(nth($args, 1)) < 2 or str-slice(nth($args, 1), 0, 2) != '--') {
        @error "Variable name is expected to start from '--'";
    }

    // PROCESS
    $varName: nth($args, 1);
    $varValue: map-get($css-vars, $varName);

    @if ($css-vars-debug-log or not $css-vars-use-native) {
        // Sass or debug
        @if ($varValue==null) {
            // variable is not provided so far
            @if (length($args) ==2) {
                // the default value is passed
                @if ($css-vars-debug-log) {
                    @debug "Provided default value is used for the variable: '#{$varName}'";
                }
                $varValue: nth($args, 2);
            } @else if ($css-vars-debug-log) {
                @debug "Variable '#{$varName}' is not assigned";
                @if (not $css-vars-use-native) {
                    @debug "The 'var(#{$varName}...)' usage will be skipped in the output CSS";
                }
            }
        }
    }

    @if ($css-vars-use-native) {
        // CSS variables
        // Native CSS: don't process function in case of native
        @return unquote('var(' + $args + ')');
    } @else {
        // Sass: return value from the map
        @return $varValue;
    }
}

//// MIXIN ////

///
// CSS mixin to provide variables
// E.G.:
// @include css-vars((
//    --color: rebeccapurple,
//    --height: 68px,
//    --margin-top: calc(2vh + 20px)
// ));
///
@mixin css-vars($varMap: null) {
    // CHECK PARAMS
    @if ($varMap==null) {
        @error 'Map of variables is expected, instead got: null';
    }
    @if (type_of($varMap) !=map) {
        @error 'Map of variables is expected, instead got another type passed: #{type_of($varMap)}';
    }

    // PROCESS
    @if ($css-vars-debug-log or not $css-vars-use-native) {
        // Sass or debug
        // merge variables and values to the global map (provides no output)
        @each $varName, $varValue in $varMap {
            $css-vars: _cssVarAssign($varName, $varValue) !global; // store in global variable
        }
    }

    @if ($css-vars-use-native) {
        // CSS variables
        // Native CSS: assign CSS custom properties to the global scope
        @at-root :root {
            @each $varName, $varValue in $varMap {
                @if (type_of($varValue) ==string) {
                    #{$varName}: $varValue; // to prevent quotes interpolation
                } @else {
                    #{$varName}: #{$varValue};
                }
            }
        }
    }
}