gerillass 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/SKILL.md +57 -5
- package/gerillass.json +315 -66
- package/package.json +1 -1
- package/scss/library/_after.scss +15 -0
- package/scss/library/_all-text-inputs.scss +1 -1
- package/scss/library/_background-dots.scss +55 -9
- package/scss/library/_background-image.scss +31 -5
- package/scss/library/_background-stripes.scss +43 -4
- package/scss/library/_before.scss +15 -0
- package/scss/library/_border-radius.scss +25 -1
- package/scss/library/_brand-logo.scss +24 -1
- package/scss/library/_breakpoint.scss +34 -0
- package/scss/library/_container-query.scss +73 -1
- package/scss/library/_counter.scss +24 -2
- package/scss/library/_focus-ring.scss +34 -0
- package/scss/library/_font-face.scss +61 -3
- package/scss/library/_index.scss +3 -0
- package/scss/library/_line-clamp.scss +14 -1
- package/scss/library/_loadify.scss +7 -0
- package/scss/library/_motion-safe.scss +28 -0
- package/scss/library/_remove.scss +4 -1
- package/scss/library/_reset-css.scss +7 -5
- package/scss/library/_screen-agent.scss +27 -0
- package/scss/library/_text-image.scss +24 -1
- package/scss/library/_tokens.scss +111 -0
- package/scss/library/_triangle.scss +109 -9
- package/scss/utilities/_clear-unit.scss +4 -0
- package/scss/utilities/_convert-to-em.scss +6 -0
- package/scss/utilities/_convert-to-number.scss +15 -0
- package/scss/utilities/_font-sizer.scss +14 -0
- package/scss/utilities/_remify.scss +7 -0
- package/scss/utilities/_validate-length.scss +7 -0
- package/scss/utilities/_validate-ratio.scss +25 -2
package/package.json
CHANGED
package/scss/library/_after.scss
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
+
@use "sass:list";
|
|
3
4
|
@use "sass:meta";
|
|
4
5
|
@use "sass:string";
|
|
5
6
|
|
|
7
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
8
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
9
|
+
@function -is-css-function($value, $names) {
|
|
10
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
11
|
+
@return false;
|
|
12
|
+
}
|
|
13
|
+
$open: string.index($value, "(");
|
|
14
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
@mixin after($content: null) {
|
|
7
18
|
&::after {
|
|
8
19
|
@if $content == null {
|
|
9
20
|
@content;
|
|
10
21
|
} @else if meta.type-of($content) != "string" {
|
|
11
22
|
@error "`#{$content}` is not a valid $content for `after`. Pass a string to use as the content value, a data- attribute name such as `\"data-label\"` to render it with attr(), or no argument at all and write the content yourself.";
|
|
23
|
+
} @else if -is-css-function($content, "var" "attr" "counter" "counters") {
|
|
24
|
+
// Quoting would turn the call into text: content: "var(--label)".
|
|
25
|
+
content: $content;
|
|
26
|
+
@content;
|
|
12
27
|
} @else {
|
|
13
28
|
$data: string.slice($content, 1, 5);
|
|
14
29
|
@if $data == "data-" {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
@use "../utilities/pseudo-selector" as *;
|
|
6
6
|
|
|
7
7
|
@mixin all-text-inputs($pseudo: null) {
|
|
8
|
-
$list: "hover", "focus", "active", "invalid", "required", "disabled";
|
|
8
|
+
$list: "hover", "focus", "focus-visible", "active", "invalid", "user-invalid", "required", "disabled";
|
|
9
9
|
@if not $pseudo {
|
|
10
10
|
#{$list-of-text-inputs} {
|
|
11
11
|
@content;
|
|
@@ -1,17 +1,63 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
3
|
@use "sass:list";
|
|
4
|
-
@use "sass:math";
|
|
5
4
|
@use "sass:meta";
|
|
6
5
|
@use "sass:string";
|
|
7
6
|
|
|
7
|
+
// An image path goes into url(). A var(), url(), image-set() or gradient is
|
|
8
|
+
// already an image, and wrapping it produced url(var(--x)), which loads nothing.
|
|
9
|
+
@function -image($value) {
|
|
10
|
+
@if -is-css-function($value, "var" "url" "image-set" "linear-gradient" "radial-gradient" "conic-gradient" "repeating-linear-gradient" "repeating-radial-gradient" "repeating-conic-gradient") {
|
|
11
|
+
@return $value;
|
|
12
|
+
}
|
|
13
|
+
@return url(string.unquote($value));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
17
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
18
|
+
@function -is-css-function($value, $names) {
|
|
19
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
20
|
+
@return false;
|
|
21
|
+
}
|
|
22
|
+
$open: string.index($value, "(");
|
|
23
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// A size Sass can use inside calc(): a number, a calculation such as calc(),
|
|
27
|
+
// min() or clamp(), or var() and env(), which only the browser can resolve.
|
|
28
|
+
// Anything else would pass silently through calc(): `calc(nonsense * 5)`
|
|
29
|
+
// compiles.
|
|
30
|
+
@function -is-size($value) {
|
|
31
|
+
@if meta.type-of($value) == "number" or meta.type-of($value) == "calculation" {
|
|
32
|
+
@return true;
|
|
33
|
+
}
|
|
34
|
+
@if meta.type-of($value) == "string" and string.slice(meta.inspect($value), 1, 1) != "\"" {
|
|
35
|
+
$open: string.index($value, "(");
|
|
36
|
+
@return $open != null and list.index("var" "env", string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
37
|
+
}
|
|
38
|
+
@return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
8
41
|
@mixin background-dots(
|
|
9
42
|
$color: null,
|
|
10
43
|
$size: 1em,
|
|
11
|
-
$gutter:
|
|
44
|
+
$gutter: null,
|
|
12
45
|
$diagonal: true,
|
|
13
46
|
$image: null
|
|
14
47
|
) {
|
|
48
|
+
// The gutter defaults to five times the size. Deriving it here rather than in
|
|
49
|
+
// the signature lets $size be checked first, and doing the arithmetic in
|
|
50
|
+
// calc() lets var() and clamp() through: Sass simplifies calc() on plain
|
|
51
|
+
// numbers back to a number, so a call with lengths emits the same CSS.
|
|
52
|
+
@if not -is-size($size) {
|
|
53
|
+
@error "`#{meta.inspect($size)}` is not a valid $size for `background-dots`. Pass a length, or var(), env() or a calculation such as `clamp()`.";
|
|
54
|
+
}
|
|
55
|
+
@if $gutter == null {
|
|
56
|
+
$gutter: calc($size * 5);
|
|
57
|
+
}
|
|
58
|
+
@if not -is-size($gutter) {
|
|
59
|
+
@error "`#{meta.inspect($gutter)}` is not a valid $gutter for `background-dots`. Pass a length, or var(), env() or a calculation such as `calc()`.";
|
|
60
|
+
}
|
|
15
61
|
@if $image != null and meta.type-of($image) != "string" {
|
|
16
62
|
@error "`#{$image}` is not a valid $image for `background-dots`. Pass an image path as a string.";
|
|
17
63
|
}
|
|
@@ -23,21 +69,21 @@
|
|
|
23
69
|
@if $diagonal == true {
|
|
24
70
|
background-image: radial-gradient($color $size, transparent 0),
|
|
25
71
|
radial-gradient($color $size, transparent 0);
|
|
26
|
-
background-position:
|
|
27
|
-
($gutter * 2) ($gutter * 2);
|
|
72
|
+
background-position: calc($gutter / 2) calc($gutter / 2),
|
|
73
|
+
calc($gutter * 2) calc($gutter * 2);
|
|
28
74
|
} @else if $diagonal == false {
|
|
29
75
|
background-image: radial-gradient($color $size, transparent 0);
|
|
30
|
-
background-position:
|
|
76
|
+
background-position: calc($gutter / 2) calc($gutter / 2);
|
|
31
77
|
}
|
|
32
78
|
} @else if $color {
|
|
33
79
|
@if $diagonal == true {
|
|
34
80
|
background-image: radial-gradient(list.nth($color, 1) $size, transparent 0),
|
|
35
81
|
radial-gradient(list.nth($color, list.length($color)) $size, transparent 0);
|
|
36
|
-
background-position:
|
|
37
|
-
($gutter * 2) ($gutter * 2);
|
|
82
|
+
background-position: calc($gutter / 2) calc($gutter / 2),
|
|
83
|
+
calc($gutter * 2) calc($gutter * 2);
|
|
38
84
|
} @else if $diagonal == false {
|
|
39
85
|
background-image: radial-gradient(list.nth($color, 1) $size, transparent 0);
|
|
40
|
-
background-position:
|
|
86
|
+
background-position: calc($gutter / 2) calc($gutter / 2);
|
|
41
87
|
@if list.length($color) > 1 {
|
|
42
88
|
@error "Please do not pass more than one argument when you disable 'diagonal' property! Simply remove the argument(s) after '#{list.nth($color, 1)}' to resolve the problem.";
|
|
43
89
|
}
|
|
@@ -55,7 +101,7 @@
|
|
|
55
101
|
height: 100%;
|
|
56
102
|
top: 0;
|
|
57
103
|
left: 0;
|
|
58
|
-
background-image:
|
|
104
|
+
background-image: -image($image);
|
|
59
105
|
background-repeat: no-repeat;
|
|
60
106
|
background-position: center;
|
|
61
107
|
background-size: cover;
|
|
@@ -4,19 +4,45 @@
|
|
|
4
4
|
@use "sass:map";
|
|
5
5
|
@use "sass:math";
|
|
6
6
|
@use "sass:meta";
|
|
7
|
+
@use "sass:string";
|
|
7
8
|
@use "../library/linear-gradient" as *;
|
|
8
9
|
@use "../maps/map-for-directions" as *;
|
|
9
10
|
|
|
11
|
+
// An image path goes into url(). A var(), url(), image-set() or gradient is
|
|
12
|
+
// already an image, and wrapping it produced url(var(--x)), which loads nothing.
|
|
13
|
+
@function -image($value) {
|
|
14
|
+
@if -is-css-function($value, "var" "url" "image-set" "linear-gradient" "radial-gradient" "conic-gradient" "repeating-linear-gradient" "repeating-radial-gradient" "repeating-conic-gradient") {
|
|
15
|
+
@return $value;
|
|
16
|
+
}
|
|
17
|
+
@return url($value);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
21
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
22
|
+
@function -is-css-function($value, $names) {
|
|
23
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
24
|
+
@return false;
|
|
25
|
+
}
|
|
26
|
+
$open: string.index($value, "(");
|
|
27
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
28
|
+
}
|
|
29
|
+
|
|
10
30
|
@mixin background-image(
|
|
11
31
|
$image-url: null,
|
|
12
32
|
$filter-color: null,
|
|
13
33
|
$filter-direction: null
|
|
14
34
|
) {
|
|
35
|
+
// The direction used to be read only when there were two or more colours,
|
|
36
|
+
// so with one colour any value was dropped without a word, a typo included.
|
|
37
|
+
// Check it first, against what the gradient branches accept.
|
|
38
|
+
@if $filter-direction and not map.has-key($map-for-directions, $filter-direction) and not (meta.type-of($filter-direction) == "number" and math.unit($filter-direction) == "deg") {
|
|
39
|
+
@error "`#{$filter-direction}` is not a valid $filter-direction. Pass an angle such as `45deg`, or one of: #{map.keys($map-for-directions)}.";
|
|
40
|
+
}
|
|
15
41
|
@if $image-url {
|
|
16
42
|
@if $filter-color {
|
|
17
43
|
@if list.length($filter-color) == 1 {
|
|
18
44
|
background-image: linear-gradient(to top, $filter-color, $filter-color),
|
|
19
|
-
|
|
45
|
+
-image($image-url);
|
|
20
46
|
} @else if list.length($filter-color) > 1 {
|
|
21
47
|
$color-list: ();
|
|
22
48
|
@for $i from 1 through list.length($filter-color) {
|
|
@@ -28,22 +54,22 @@
|
|
|
28
54
|
map.get($map-for-directions, $filter-direction),
|
|
29
55
|
$color-list
|
|
30
56
|
),
|
|
31
|
-
|
|
57
|
+
-image($image-url);
|
|
32
58
|
} @else {
|
|
33
59
|
@if meta.type-of($filter-direction) == "number" and list.index("deg", math.unit($filter-direction)) {
|
|
34
60
|
background-image: linear-gradient($filter-direction, $color-list),
|
|
35
|
-
|
|
61
|
+
-image($image-url);
|
|
36
62
|
} @else {
|
|
37
63
|
@error "`#{$filter-direction}` is not a valid $filter-direction. Pass an angle such as `45deg`, or one of: #{map.keys($map-for-directions)}.";
|
|
38
64
|
}
|
|
39
65
|
}
|
|
40
66
|
} @else {
|
|
41
67
|
background-image: linear-gradient(to top, $color-list),
|
|
42
|
-
|
|
68
|
+
-image($image-url);
|
|
43
69
|
}
|
|
44
70
|
}
|
|
45
71
|
} @else {
|
|
46
|
-
background-image:
|
|
72
|
+
background-image: -image($image-url);
|
|
47
73
|
}
|
|
48
74
|
} @else {
|
|
49
75
|
position: relative;
|
|
@@ -5,12 +5,51 @@
|
|
|
5
5
|
@use "sass:meta";
|
|
6
6
|
@use "sass:string";
|
|
7
7
|
|
|
8
|
+
// An image path goes into url(). A var(), url(), image-set() or gradient is
|
|
9
|
+
// already an image, and wrapping it produced url(var(--x)), which loads nothing.
|
|
10
|
+
@function -image($value) {
|
|
11
|
+
@if -is-css-function($value, "var" "url" "image-set" "linear-gradient" "radial-gradient" "conic-gradient" "repeating-linear-gradient" "repeating-radial-gradient" "repeating-conic-gradient") {
|
|
12
|
+
@return $value;
|
|
13
|
+
}
|
|
14
|
+
@return url(string.unquote($value));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
18
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
19
|
+
@function -is-css-function($value, $names) {
|
|
20
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
21
|
+
@return false;
|
|
22
|
+
}
|
|
23
|
+
$open: string.index($value, "(");
|
|
24
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// A size Sass can use inside calc(): a number, a calculation such as calc(),
|
|
28
|
+
// min() or clamp(), or var() and env(), which only the browser can resolve.
|
|
29
|
+
// Anything else would pass silently through calc(): `calc(nonsense * 5)`
|
|
30
|
+
// compiles.
|
|
31
|
+
@function -is-size($value) {
|
|
32
|
+
@if meta.type-of($value) == "number" or meta.type-of($value) == "calculation" {
|
|
33
|
+
@return true;
|
|
34
|
+
}
|
|
35
|
+
@if meta.type-of($value) == "string" and string.slice(meta.inspect($value), 1, 1) != "\"" {
|
|
36
|
+
$open: string.index($value, "(");
|
|
37
|
+
@return $open != null and list.index("var" "env", string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
38
|
+
}
|
|
39
|
+
@return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
8
42
|
@mixin background-stripes(
|
|
9
43
|
$color: null,
|
|
10
44
|
$thickness: 1em,
|
|
11
45
|
$rotation: -45deg,
|
|
12
46
|
$image: null
|
|
13
47
|
) {
|
|
48
|
+
// The arithmetic below runs in calc() so var() and clamp() work; on plain
|
|
49
|
+
// lengths Sass simplifies it back to the same number.
|
|
50
|
+
@if not -is-size($thickness) {
|
|
51
|
+
@error "`#{meta.inspect($thickness)}` is not a valid $thickness for `background-stripes`. Pass a length, or var(), env() or a calculation such as `clamp()`.";
|
|
52
|
+
}
|
|
14
53
|
@if meta.type-of($rotation) != "number" {
|
|
15
54
|
@error "`#{$rotation}` is not a valid $rotation for `background-stripes`. Pass an angle such as `-45deg`, or a unitless number which is treated as degrees.";
|
|
16
55
|
}
|
|
@@ -18,7 +57,7 @@
|
|
|
18
57
|
@error "`#{$image}` is not a valid $image for `background-stripes`. Pass an image path as a string.";
|
|
19
58
|
}
|
|
20
59
|
$validate-unit: if(not list.index("deg", math.unit($rotation)), $rotation + deg, $rotation);
|
|
21
|
-
$get-image: if($image, string.unquote(", ") +
|
|
60
|
+
$get-image: if($image, string.unquote(", ") + -image($image), string.unquote(""));
|
|
22
61
|
@if not $color {
|
|
23
62
|
$color: rgba(0, 0, 0, 0.1);
|
|
24
63
|
background-image: repeating-linear-gradient(
|
|
@@ -26,7 +65,7 @@
|
|
|
26
65
|
$color 0,
|
|
27
66
|
$color $thickness,
|
|
28
67
|
transparent $thickness,
|
|
29
|
-
transparent $thickness * 2
|
|
68
|
+
transparent calc($thickness * 2)
|
|
30
69
|
) + $get-image;
|
|
31
70
|
@if $image {
|
|
32
71
|
background-position: center;
|
|
@@ -39,7 +78,7 @@
|
|
|
39
78
|
$color 0,
|
|
40
79
|
$color $thickness,
|
|
41
80
|
transparent $thickness,
|
|
42
|
-
transparent $thickness * 2
|
|
81
|
+
transparent calc($thickness * 2)
|
|
43
82
|
) + $get-image;
|
|
44
83
|
@if $image {
|
|
45
84
|
background-position: center;
|
|
@@ -50,7 +89,7 @@
|
|
|
50
89
|
$list: ();
|
|
51
90
|
@for $i from 1 through list.length($color) {
|
|
52
91
|
$index-color: list.nth($color, $i);
|
|
53
|
-
$style-rule: $index-color ($thickness * $i
|
|
92
|
+
$style-rule: $index-color calc($thickness * $i - $thickness), $index-color calc($thickness * $i);
|
|
54
93
|
$list: list.append($list, $style-rule, comma);
|
|
55
94
|
}
|
|
56
95
|
background-image: repeating-linear-gradient($validate-unit, $list) + $get-image;
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
+
@use "sass:list";
|
|
3
4
|
@use "sass:meta";
|
|
4
5
|
@use "sass:string";
|
|
5
6
|
|
|
7
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
8
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
9
|
+
@function -is-css-function($value, $names) {
|
|
10
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
11
|
+
@return false;
|
|
12
|
+
}
|
|
13
|
+
$open: string.index($value, "(");
|
|
14
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
@mixin before($content: null) {
|
|
7
18
|
&::before {
|
|
8
19
|
@if $content == null {
|
|
9
20
|
@content;
|
|
10
21
|
} @else if meta.type-of($content) != "string" {
|
|
11
22
|
@error "`#{$content}` is not a valid $content for `before`. Pass a string to use as the content value, a data- attribute name such as `\"data-label\"` to render it with attr(), or no argument at all and write the content yourself.";
|
|
23
|
+
} @else if -is-css-function($content, "var" "attr" "counter" "counters") {
|
|
24
|
+
// Quoting would turn the call into text: content: "var(--label)".
|
|
25
|
+
content: $content;
|
|
26
|
+
@content;
|
|
12
27
|
} @else {
|
|
13
28
|
$data: string.slice($content, 1, 5);
|
|
14
29
|
@if $data == "data-" {
|
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
@use "../utilities/fill-nulls" as *;
|
|
6
6
|
|
|
7
7
|
@mixin border-radius($args...) {
|
|
8
|
-
|
|
8
|
+
// Logical corners are named block side first, inline side second, like the
|
|
9
|
+
// properties they map to. Every name here needs a branch below: the chain has
|
|
10
|
+
// no final @else, so a name without one would be accepted and emit nothing.
|
|
11
|
+
$logical: ("start-start", "start-end", "end-start", "end-end", "inline-start", "inline-end", "block-start", "block-end");
|
|
12
|
+
$list: list.join(list.join($list-of-directions, ("cross-left", "cross-right", "all")), $logical);
|
|
9
13
|
@if list.length($args) == 1 {
|
|
10
14
|
$value: list.nth($args, 1);
|
|
11
15
|
border-radius: fillNulls($value, space);
|
|
@@ -41,6 +45,26 @@
|
|
|
41
45
|
} @else if $corner == "cross-right" {
|
|
42
46
|
border-top-right-radius: $value;
|
|
43
47
|
border-bottom-left-radius: $value;
|
|
48
|
+
} @else if $corner == "start-start" {
|
|
49
|
+
border-start-start-radius: $value;
|
|
50
|
+
} @else if $corner == "start-end" {
|
|
51
|
+
border-start-end-radius: $value;
|
|
52
|
+
} @else if $corner == "end-start" {
|
|
53
|
+
border-end-start-radius: $value;
|
|
54
|
+
} @else if $corner == "end-end" {
|
|
55
|
+
border-end-end-radius: $value;
|
|
56
|
+
} @else if $corner == "inline-start" {
|
|
57
|
+
border-start-start-radius: $value;
|
|
58
|
+
border-end-start-radius: $value;
|
|
59
|
+
} @else if $corner == "inline-end" {
|
|
60
|
+
border-start-end-radius: $value;
|
|
61
|
+
border-end-end-radius: $value;
|
|
62
|
+
} @else if $corner == "block-start" {
|
|
63
|
+
border-start-start-radius: $value;
|
|
64
|
+
border-start-end-radius: $value;
|
|
65
|
+
} @else if $corner == "block-end" {
|
|
66
|
+
border-end-start-radius: $value;
|
|
67
|
+
border-end-end-radius: $value;
|
|
44
68
|
}
|
|
45
69
|
} @else {
|
|
46
70
|
@error "Corner value must be one of the followings: #{$list}.";
|
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
@use "sass:string";
|
|
6
|
+
|
|
3
7
|
@use "../library/stretched-link" as *;
|
|
4
8
|
|
|
9
|
+
// An image path goes into url(). A var(), url(), image-set() or gradient is
|
|
10
|
+
// already an image, and wrapping it produced url(var(--x)), which loads nothing.
|
|
11
|
+
@function -image($value) {
|
|
12
|
+
@if -is-css-function($value, "var" "url" "image-set" "linear-gradient" "radial-gradient" "conic-gradient" "repeating-linear-gradient" "repeating-radial-gradient" "repeating-conic-gradient") {
|
|
13
|
+
@return $value;
|
|
14
|
+
}
|
|
15
|
+
@return url($value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
19
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
20
|
+
@function -is-css-function($value, $names) {
|
|
21
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
22
|
+
@return false;
|
|
23
|
+
}
|
|
24
|
+
$open: string.index($value, "(");
|
|
25
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
26
|
+
}
|
|
27
|
+
|
|
5
28
|
@mixin brand-logo($width, $height, $image-url: null) {
|
|
6
29
|
display: inline-block;
|
|
7
30
|
position: relative;
|
|
8
31
|
width: $width;
|
|
9
32
|
height: $height;
|
|
10
33
|
@if $image-url {
|
|
11
|
-
background-image:
|
|
34
|
+
background-image: -image($image-url);
|
|
12
35
|
}
|
|
13
36
|
background-position: center;
|
|
14
37
|
background-repeat: no-repeat;
|
|
@@ -2,12 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
@use "sass:list";
|
|
4
4
|
@use "sass:map";
|
|
5
|
+
@use "sass:meta";
|
|
6
|
+
@use "sass:string";
|
|
5
7
|
@use "../maps/map-for-breakpoints" as *;
|
|
6
8
|
@use "../utilities/validate-breakpoint" as *;
|
|
7
9
|
|
|
10
|
+
// Returns the first value in $value that holds var(), looking inside lists and
|
|
11
|
+
// calculations, or null. Custom properties are not evaluated in a @media or
|
|
12
|
+
// @container condition, so a rule built from one never applies, and nothing
|
|
13
|
+
// warns. Measured in Chrome 152: `(min-width: var(--wide))` did not match with
|
|
14
|
+
// `--wide: 200px`, while `(min-width: 200px)` did.
|
|
15
|
+
@function -custom-property-in($value) {
|
|
16
|
+
@each $item in $value {
|
|
17
|
+
@if meta.type-of($item) == "list" or meta.type-of($item) == "arglist" {
|
|
18
|
+
$found: -custom-property-in($item);
|
|
19
|
+
@if $found {
|
|
20
|
+
@return $found;
|
|
21
|
+
}
|
|
22
|
+
} @else if string.index(meta.inspect($item), "var(") {
|
|
23
|
+
@return $item;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
@return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
8
29
|
@mixin breakpoint($params...) {
|
|
30
|
+
$custom-property: -custom-property-in($params);
|
|
31
|
+
@if $custom-property {
|
|
32
|
+
@error "`#{$custom-property}` cannot be used in a breakpoint: custom properties are not evaluated in a @media condition, so the rule would never apply. Pass a length or a key from $map-for-breakpoints.";
|
|
33
|
+
}
|
|
9
34
|
@if list.length($params) == 1 {
|
|
10
35
|
$value: list.nth($params, 1);
|
|
36
|
+
$width: if(map.has-key($map-for-breakpoints, $value), map.get($map-for-breakpoints, $value), $value);
|
|
37
|
+
// One argument matches a single pixel, which two agent trials took for
|
|
38
|
+
// "from this width up". Still emitted, so no stylesheet changes, but said
|
|
39
|
+
// out loud until 3.0.0 refuses it.
|
|
40
|
+
@warn "`breakpoint(#{$value})` matches only a viewport exactly #{$width} wide, `(width: #{$width})`. Write `breakpoint(only, #{$value})` for that width, or `breakpoint(min, #{$value})` from it upwards. The one-argument form will be refused in 3.0.0.";
|
|
11
41
|
@if map.has-key($map-for-breakpoints, $value) {
|
|
12
42
|
@media (width: map.get($map-for-breakpoints, $value)) {
|
|
13
43
|
@content;
|
|
@@ -65,5 +95,9 @@
|
|
|
65
95
|
}
|
|
66
96
|
}
|
|
67
97
|
}
|
|
98
|
+
} @else {
|
|
99
|
+
// Anything else used to match no branch and emit nothing, so a three
|
|
100
|
+
// argument range such as `between, medium, large` failed without a sound.
|
|
101
|
+
@error "`breakpoint` takes one or two arguments; you passed #{list.length($params)}. For a range, pass `between` with a space-separated pair, `between, medium large`, or two sizes, `medium, large`.";
|
|
68
102
|
}
|
|
69
103
|
}
|
|
@@ -7,6 +7,64 @@
|
|
|
7
7
|
@use "../maps/map-for-breakpoints" as *;
|
|
8
8
|
@use "../utilities/validate-breakpoint" as *;
|
|
9
9
|
|
|
10
|
+
// Returns the first value in $value that holds var(), looking inside lists and
|
|
11
|
+
// calculations, or null. Custom properties are not evaluated in a @media or
|
|
12
|
+
// @container condition, so a rule built from one never applies, and nothing
|
|
13
|
+
// warns. Measured in Chrome 152: `(min-width: var(--wide))` did not match with
|
|
14
|
+
// `--wide: 200px`, while `(min-width: 200px)` did.
|
|
15
|
+
@function -custom-property-in($value) {
|
|
16
|
+
@each $item in $value {
|
|
17
|
+
@if meta.type-of($item) == "list" or meta.type-of($item) == "arglist" {
|
|
18
|
+
$found: -custom-property-in($item);
|
|
19
|
+
@if $found {
|
|
20
|
+
@return $found;
|
|
21
|
+
}
|
|
22
|
+
} @else if string.index(meta.inspect($item), "var(") {
|
|
23
|
+
@return $item;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
@return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Characters and names a browser will not keep as the name in an @container
|
|
30
|
+
// rule. Measured in Chrome 152, the rule was dropped for `var(--n)`, `none`,
|
|
31
|
+
// `and`, `or`, `default`, `inherit`, `initial`, `unset`, `revert`,
|
|
32
|
+
// `revert-layer`, `my card`, `1card`, `-1card`, `a.b`, `#card` and `card!`,
|
|
33
|
+
// in any case. `not` was worse: the rule was kept with no name, as a negated
|
|
34
|
+
// query, so it matched the opposite of what was asked. `--card`, `-card`,
|
|
35
|
+
// `_card`, `c-`, `ünlü`, `auto` and `normal` were kept.
|
|
36
|
+
$-reserved-names: "none" "and" "or" "not" "default" "inherit" "initial" "unset" "revert" "revert-layer";
|
|
37
|
+
$-forbidden-in-name: "." "," "/" "#" ":" ";" "(" ")" "[" "]" "{" "}" "!" "@" "$" "%" "^" "&" "*" "+" "=" "<" ">" "?" "\\" "|" "~" "`" "'" "\"";
|
|
38
|
+
|
|
39
|
+
@function -name-problem($name) {
|
|
40
|
+
// An empty name has always compiled to an unnamed query, which works, so it
|
|
41
|
+
// is left alone rather than refused.
|
|
42
|
+
$text: "#{$name}";
|
|
43
|
+
@if string.length($text) == 0 {
|
|
44
|
+
@return null;
|
|
45
|
+
}
|
|
46
|
+
@if string.index($text, "var(") {
|
|
47
|
+
@return "a custom property is not evaluated in a @container condition, so the rule would never apply. Pass the name itself, such as `\"card\"`; the `container` mixin can still take its name from a custom property";
|
|
48
|
+
}
|
|
49
|
+
@if string.index($text, " ") {
|
|
50
|
+
@return "a query names one container. Pass one name, such as `\"card\"`";
|
|
51
|
+
}
|
|
52
|
+
@if list.index($-reserved-names, string.to-lower-case($text)) {
|
|
53
|
+
@return "`none`, `and`, `or`, `not`, `default` and the CSS-wide keywords are reserved there. A browser drops the rule, and reads `not` as negating the query instead. Pass another name, such as `\"card\"`";
|
|
54
|
+
}
|
|
55
|
+
$first: string.slice($text, 1, 1);
|
|
56
|
+
$second: string.slice($text, 2, 2);
|
|
57
|
+
@if string.index("0123456789", $first) or ($first == "-" and string.length($text) > 1 and string.index("0123456789", $second)) {
|
|
58
|
+
@return "a container name cannot start with a digit, or with a hyphen and a digit. Pass a name such as `\"card\"`";
|
|
59
|
+
}
|
|
60
|
+
@each $character in $-forbidden-in-name {
|
|
61
|
+
@if string.index($text, $character) {
|
|
62
|
+
@return "a container name cannot contain `#{$character}`. Use letters, digits, hyphens and underscores";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
@return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
10
68
|
// A @container rule, taking the same argument shapes as `breakpoint` so the two
|
|
11
69
|
// read alike. Sizes may be a key from $map-for-breakpoints or a raw length; a
|
|
12
70
|
// container is usually narrower than the viewport, so a length is the common
|
|
@@ -23,11 +81,25 @@
|
|
|
23
81
|
@if $name != null and meta.type-of($name) != "string" {
|
|
24
82
|
@error "`#{$name}` is not a valid $name for `container-query`. Pass a container name as a string, such as `\"card\"`.";
|
|
25
83
|
}
|
|
84
|
+
@if $name != null {
|
|
85
|
+
$problem: -name-problem($name);
|
|
86
|
+
@if $problem {
|
|
87
|
+
@error "`#{$name}` is not a valid $name for `container-query`: #{$problem}.";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
26
90
|
|
|
91
|
+
$custom-property: -custom-property-in($params);
|
|
92
|
+
@if $custom-property {
|
|
93
|
+
@error "`#{$custom-property}` cannot be used in a container query: custom properties are not evaluated in a @container condition, so the rule would never apply. Pass a length or a key from $map-for-breakpoints.";
|
|
94
|
+
}
|
|
27
95
|
$condition: null;
|
|
28
96
|
|
|
29
97
|
@if $count == 1 {
|
|
30
|
-
$
|
|
98
|
+
$value: list.nth($params, 1);
|
|
99
|
+
$width: validateBreakpoint($value);
|
|
100
|
+
$condition: "(width: #{$width})";
|
|
101
|
+
// A single pixel, as in `breakpoint`; still emitted until 3.0.0 refuses it.
|
|
102
|
+
@warn "`container-query(#{$value})` matches only a container exactly #{$width} wide, `(width: #{$width})`. Write `container-query(only, #{$value})` for that width, or `container-query(min, #{$value})` from it upwards. The one-argument form will be refused in 3.0.0.";
|
|
31
103
|
} @else if $count == 2 {
|
|
32
104
|
$mode: list.nth($params, 1);
|
|
33
105
|
@if not list.index("only" "min" "max" "between", $mode) {
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
3
|
@use "sass:list";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
@use "sass:string";
|
|
4
6
|
@use "../lists/list-of-counter-styles" as *;
|
|
5
7
|
|
|
8
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
9
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
10
|
+
@function -is-css-function($value, $names) {
|
|
11
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
12
|
+
@return false;
|
|
13
|
+
}
|
|
14
|
+
$open: string.index($value, "(");
|
|
15
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
16
|
+
}
|
|
17
|
+
|
|
6
18
|
@mixin counter($params...) {
|
|
7
19
|
$counter: null;
|
|
8
20
|
$counter-before: null;
|
|
@@ -33,15 +45,25 @@
|
|
|
33
45
|
}
|
|
34
46
|
}
|
|
35
47
|
|
|
48
|
+
// A prefix or suffix is quoted into text, except a call CSS resolves, which
|
|
49
|
+
// quoting would turn into the literal characters.
|
|
50
|
+
$quote-before: '"';
|
|
51
|
+
$quote-after: '"';
|
|
52
|
+
@if -is-css-function($counter-before, "var" "attr" "counter" "counters") {
|
|
53
|
+
$quote-before: "";
|
|
54
|
+
}
|
|
55
|
+
@if -is-css-function($counter-after, "var" "attr" "counter" "counters") {
|
|
56
|
+
$quote-after: "";
|
|
57
|
+
}
|
|
36
58
|
&.counter-start {
|
|
37
59
|
counter-reset: glsCounter;
|
|
38
60
|
}
|
|
39
61
|
&.counter-start .counter-item::before,
|
|
40
62
|
&.counter-continue .counter-item::before {
|
|
41
|
-
content: #{if($counter-before,
|
|
63
|
+
content: #{if($counter-before, $quote-before + $counter-before + $quote-before + " ", null)}counter(
|
|
42
64
|
glsCounter#{if($counter, ", " + $counter, null)}
|
|
43
65
|
)
|
|
44
|
-
#{if($counter-after, " " +
|
|
66
|
+
#{if($counter-after, " " + $quote-after + $counter-after + $quote-after, null)};
|
|
45
67
|
counter-increment: glsCounter;
|
|
46
68
|
@content;
|
|
47
69
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
// Draws a focus ring for keyboard users. Two things are usually got wrong by
|
|
4
|
+
// hand, and this writes the version that avoids both.
|
|
5
|
+
//
|
|
6
|
+
// The ring goes on :focus-visible, not :focus. Measured in Chrome 152: a mouse
|
|
7
|
+
// click on a button or a link does not match :focus-visible, so the ring stays
|
|
8
|
+
// out of the way of pointer users, while Tab does match it. Text inputs are the
|
|
9
|
+
// exception and match it on a click too, which is the browser's own choice.
|
|
10
|
+
// Hiding the ring with `:focus { outline: none; }` is the common mistake it
|
|
11
|
+
// replaces: tabbing to that button gave no outline and no shadow at all.
|
|
12
|
+
//
|
|
13
|
+
// The ring is an outline, not a box-shadow. A box-shadow ring looks the same
|
|
14
|
+
// in an ordinary page, but forced-colors mode, as Windows High Contrast is
|
|
15
|
+
// exposed to CSS, sets box-shadow to none and repaints outline-color in a
|
|
16
|
+
// system colour, so a shadow ring vanishes for the users who most need it.
|
|
17
|
+
// That part follows the CSS Color Adjustment specification; it was not
|
|
18
|
+
// measured here, because the browser used could not emulate the mode.
|
|
19
|
+
//
|
|
20
|
+
// Two things measured about the outline itself. It follows border-radius: on a
|
|
21
|
+
// button with a 12px radius the ring is rounded to match. And an ancestor with
|
|
22
|
+
// overflow: hidden clips it: a 2px offset left only the ring's corners showing,
|
|
23
|
+
// while an offset of -4px drew it inside the element, fully visible. Pass a
|
|
24
|
+
// negative $offset where the element sits in a clipping container.
|
|
25
|
+
@mixin focus-ring($width: 2px, $offset: 2px, $color: currentColor) {
|
|
26
|
+
@if not & {
|
|
27
|
+
@error "`focus-ring` styles the element it is called in, so call it inside a selector, such as `.button { @include focus-ring; }`.";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&:focus-visible {
|
|
31
|
+
outline: $width solid $color;
|
|
32
|
+
outline-offset: $offset;
|
|
33
|
+
}
|
|
34
|
+
}
|