1 | //
|
2 | // Copyright 2020 Google Inc.
|
3 | //
|
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 | // of this software and associated documentation files (the "Software"), to deal
|
6 | // in the Software without restriction, including without limitation the rights
|
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 | // copies of the Software, and to permit persons to whom the Software is
|
9 | // furnished to do so, subject to the following conditions:
|
10 | //
|
11 | // The above copyright notice and this permission notice shall be included in
|
12 | // all copies or substantial portions of the Software.
|
13 | //
|
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 | // THE SOFTWARE.
|
21 | //
|
22 |
|
23 | @use 'sass:list';
|
24 | @use 'sass:map';
|
25 | @use 'sass:meta';
|
26 | @use './gss';
|
27 |
|
28 | /// When true, add an additional property/value declaration before declarations
|
29 | /// that use advanced features such as custom properties or CSS functions. This
|
30 | /// adds fallback support for older browsers such as IE11 that do not support
|
31 | /// these features at the cost of additional CSS. Set this variable to false to
|
32 | /// disable generating fallback declarations.
|
33 | $enable-fallback-declarations: true !default;
|
34 |
|
35 | /// Writes a CSS property/value declaration. This mixin is used throughout the
|
36 | /// theme package for consistency for dynamically setting CSS property values.
|
37 | ///
|
38 | /// This mixin may optionally take a fallback value. For advanced features such
|
39 | /// as custom properties or CSS functions like min and max, a fallback value is
|
40 | /// recommended to support older browsers.
|
41 | ///
|
42 | /// @param {String} $property - The CSS property of the declaration.
|
43 | /// @param {*} $value - The value of the CSS declaration. The value should be
|
44 | /// resolved by other theme functions first (i.e. custom property Maps and
|
45 | /// Material theme keys are not supported in this mixin). If the value is
|
46 | /// null, no declarations will be emitted.
|
47 | /// @param {*} $fallback - An optional fallback value for older browsers. If
|
48 | /// provided, a second property/value declaration will be added before the
|
49 | /// main property/value declaration.
|
50 | /// @param {Map} $gss - An optional Map of GSS annotations to add.
|
51 | /// @param {Bool} $important - If true, add `!important` to the declaration.
|
52 | @mixin declaration(
|
53 | $property,
|
54 | $value,
|
55 | $fallback-value: null,
|
56 | $gss: (),
|
57 | $important: false
|
58 | ) {
|
59 | // Normally setting a null value to a property will not emit CSS, so mixins
|
60 | // wouldn't need to check this. However, Sass will throw an error if the
|
61 | // interpolated property is a custom property.
|
62 | @if $value != null {
|
63 | $important-rule: if($important, ' !important', '');
|
64 |
|
65 | @if $fallback-value and $enable-fallback-declarations {
|
66 | @include gss.annotate($gss);
|
67 | #{$property}: #{$fallback-value} #{$important-rule};
|
68 |
|
69 | // Add @alternate to annotations.
|
70 | $gss: map.merge(
|
71 | $gss,
|
72 | (
|
73 | alternate: true,
|
74 | )
|
75 | );
|
76 | }
|
77 |
|
78 | @include gss.annotate($gss);
|
79 | #{$property}: #{$value}#{$important-rule};
|
80 | }
|
81 | }
|
82 |
|
83 | /// Unpacks shorthand values for CSS properties (i.e. lists of 1-3 values).
|
84 | /// If a list of 4 values is given, it is returned as-is.
|
85 | ///
|
86 | /// Examples:
|
87 | ///
|
88 | /// unpack-value(4px) => 4px 4px 4px 4px
|
89 | /// unpack-value(4px 2px) => 4px 2px 4px 2px
|
90 | /// unpack-value(4px 2px 2px) => 4px 2px 2px 2px
|
91 | /// unpack-value(4px 2px 0 2px) => 4px 2px 0 2px
|
92 | ///
|
93 | /// @param {Number | Map | List} $value - List of 1 to 4 value numbers.
|
94 | /// @return {List} a List of 4 value numbers.
|
95 | @function unpack-value($value) {
|
96 | @if meta.type-of($value) == 'map' or list.length($value) == 1 {
|
97 | @return $value $value $value $value;
|
98 | } @else if list.length($value) == 4 {
|
99 | @return $value;
|
100 | } @else if list.length($value) == 3 {
|
101 | @return list.nth($value, 1) list.nth($value, 2) list.nth($value, 3)
|
102 | list.nth($value, 2);
|
103 | } @else if list.length($value) == 2 {
|
104 | @return list.nth($value, 1) list.nth($value, 2) list.nth($value, 1)
|
105 | list.nth($value, 2);
|
106 | }
|
107 |
|
108 | @error "Invalid CSS property value: '#{$value}' is more than 4 values";
|
109 | }
|