@fest-lib/veela 0.1.1

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.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +533 -0
  3. package/dist/veela.js +878 -0
  4. package/package.json +83 -0
  5. package/src/scss/_layers.scss +16 -0
  6. package/src/scss/advanced/_index.scss +0 -0
  7. package/src/scss/advanced/animation/_motion.scss +317 -0
  8. package/src/scss/advanced/color/_color.scss +328 -0
  9. package/src/scss/advanced/color/_colorize.scss +325 -0
  10. package/src/scss/advanced/design/_design-tokens.scss +118 -0
  11. package/src/scss/advanced/design/_effects.scss +275 -0
  12. package/src/scss/advanced/design/_shadow.scss +359 -0
  13. package/src/scss/advanced/design/_surfaces.scss +76 -0
  14. package/src/scss/advanced/effects/_animations.scss +124 -0
  15. package/src/scss/advanced/effects/_shadows.scss +50 -0
  16. package/src/scss/advanced/font/_typography.scss +600 -0
  17. package/src/scss/advanced/index.scss +11 -0
  18. package/src/scss/advanced/index.ts +35 -0
  19. package/src/scss/advanced/layout/_content.scss +170 -0
  20. package/src/scss/advanced/layout/_index.scss +5 -0
  21. package/src/scss/advanced/layout/_normalize.scss +541 -0
  22. package/src/scss/advanced/layout/_shared-overlays.scss +162 -0
  23. package/src/scss/advanced/md3/_md3.scss +596 -0
  24. package/src/scss/advanced/md3/_utils.scss +114 -0
  25. package/src/scss/advanced/misc/_config.scss +119 -0
  26. package/src/scss/advanced/misc/_initials.scss +298 -0
  27. package/src/scss/advanced/misc/_mixins.scss +179 -0
  28. package/src/scss/advanced/misc/_queries.scss +34 -0
  29. package/src/scss/advanced/misc/_rendering.scss +82 -0
  30. package/src/scss/advanced/misc/_tokens.scss +74 -0
  31. package/src/scss/advanced/theme/_shared.scss +232 -0
  32. package/src/scss/advanced/theme/_states.scss +332 -0
  33. package/src/scss/advanced/theme/_variants.scss +354 -0
  34. package/src/scss/advanced/tokens/_material-color.scss +120 -0
  35. package/src/scss/advanced/tokens/_variables.scss +171 -0
  36. package/src/scss/basic/_layers.scss +0 -0
  37. package/src/scss/basic/design/_index.scss +3 -0
  38. package/src/scss/basic/design/_keyframes.scss +163 -0
  39. package/src/scss/basic/design/_shapes.scss +266 -0
  40. package/src/scss/basic/design/_wavy-runtime.scss +50 -0
  41. package/src/scss/basic/index.scss +19 -0
  42. package/src/scss/basic/index.ts +29 -0
  43. package/src/scss/basic/misc/_core-layout.scss +272 -0
  44. package/src/scss/basic/misc/_index.scss +18 -0
  45. package/src/scss/basic/misc/_layout.scss +1040 -0
  46. package/src/scss/basic/misc/_mixins.scss +179 -0
  47. package/src/scss/basic/misc/_motion.scss +28 -0
  48. package/src/scss/basic/misc/_normalize.scss +765 -0
  49. package/src/scss/basic/misc/_queries.scss +34 -0
  50. package/src/scss/basic/misc/_shared.scss +232 -0
  51. package/src/scss/basic/misc/_states.scss +135 -0
  52. package/src/scss/basic/misc/_tokens.scss +78 -0
  53. package/src/scss/basic/misc/_veela.scss +12 -0
  54. package/src/scss/core/index.scss +1 -0
  55. package/src/scss/core/interact/_draggable.scss +32 -0
  56. package/src/scss/core/interact/_position.scss +45 -0
  57. package/src/scss/core/interact/_ps-anchor.scss +28 -0
  58. package/src/scss/core/interact/_ps-centered.scss +28 -0
  59. package/src/scss/core/interact/_ps-cursor.scss +18 -0
  60. package/src/scss/core/interact/_ps-draggable.scss +25 -0
  61. package/src/scss/core/interact/_ps-mechanic.scss +0 -0
  62. package/src/scss/core/interact/_ps-properties.scss +54 -0
  63. package/src/scss/core/interact/_ps-resizable.scss +61 -0
  64. package/src/scss/core/interact/_resizable.scss +69 -0
  65. package/src/scss/core/interact/_viewport.scss +469 -0
  66. package/src/scss/core/misc/_color-properties.scss +64 -0
  67. package/src/scss/core/misc/_config.scss +110 -0
  68. package/src/scss/core/misc/_functions.scss +530 -0
  69. package/src/scss/core/misc/_icons.scss +109 -0
  70. package/src/scss/core/misc/_index.scss +6 -0
  71. package/src/scss/core/misc/_layout.scss +49 -0
  72. package/src/scss/core/misc/_mixins.scss +744 -0
  73. package/src/scss/core/misc/_properties.scss +245 -0
  74. package/src/scss/core/misc/_tokens.scss +947 -0
  75. package/src/scss/core/misc/_utilities.scss +941 -0
  76. package/src/scss/core/misc/_utils.scss +17 -0
  77. package/src/scss/index.scss +18 -0
  78. package/src/scss/index.ts +105 -0
@@ -0,0 +1,64 @@
1
+ /*
2
+ * Filename: _color-properties.scss
3
+ * FullPath: modules/projects/veela.css/src/scss/core/misc/_color-properties.scss
4
+ * Change date and time: 09.05.00_02.08.2026
5
+ * Reason for changes: Only seed hues as @property — semantic light-dark() must stay unregistered.
6
+ */
7
+
8
+ /*
9
+ * INVARIANT: Do NOT register `--color-surface` / `--color-on-surface` / etc. as `@property <color>`.
10
+ * WHY: Typed colors compute `light-dark()` on the defining element (:root) and inherit a *concrete*
11
+ * color. Children that lock `color-scheme: light` then get cream surfaces (local light-dark) but
12
+ * keep light-on-dark text from the inherited computed token — Settings Appearance labels vanish.
13
+ *
14
+ * Seeds only: WallpaperTheme / Quick Settings write these; surfaces derive via unregistered
15
+ * `light-dark(--u2-color-mod(...))` in `_tokens.scss` and re-evaluate per used color-scheme.
16
+ */
17
+
18
+ @property --color-primary {
19
+ syntax: "<color>";
20
+ inherits: true;
21
+ initial-value: #5a7fff;
22
+ }
23
+
24
+ @property --base-color {
25
+ syntax: "<color>";
26
+ inherits: true;
27
+ initial-value: #5a7fff;
28
+ }
29
+
30
+ @property --color-secondary {
31
+ syntax: "<color>";
32
+ inherits: true;
33
+ initial-value: #6b8cff;
34
+ }
35
+
36
+ @property --color-tertiary {
37
+ syntax: "<color>";
38
+ inherits: true;
39
+ initial-value: #8aa0ff;
40
+ }
41
+
42
+ @property --color-error {
43
+ syntax: "<color>";
44
+ inherits: true;
45
+ initial-value: #ef4444;
46
+ }
47
+
48
+ @property --color-success {
49
+ syntax: "<color>";
50
+ inherits: true;
51
+ initial-value: #4caf50;
52
+ }
53
+
54
+ @property --color-warning {
55
+ syntax: "<color>";
56
+ inherits: true;
57
+ initial-value: #ff9800;
58
+ }
59
+
60
+ @property --color-info {
61
+ syntax: "<color>";
62
+ inherits: true;
63
+ initial-value: #2196f3;
64
+ }
@@ -0,0 +1,110 @@
1
+ @use "sass:map";
2
+ @use "sass:list";
3
+
4
+ //
5
+ $md-config: (
6
+ "effects": (
7
+ "active-brightness": 0.95,
8
+ "hover-brightness": 0.96
9
+ ),
10
+ "shape": (
11
+ "border-radius": 8px,
12
+ "box-shadow": 0 1px 3px rgba(0,0,0,0.12),
13
+ "box-shadow-card": 0 4px 6px -1px rgba(0, 0, 0, 0.1),
14
+ ),
15
+ "colors": (
16
+ "accent": (#0969da, #2f81f7),
17
+ "bg": (#ffffff, #0d1117),
18
+ "bg-subtle": (#f6f8fa, #161b22),
19
+ "bg-secondary": (#f6f8fa, #161b22),
20
+ "border": (#d0d7de, #30363d),
21
+ "border-subtle": (#eff1f3, #21262d),
22
+ "link": (#0969da, #2f81f7),
23
+ "text": (#1f2328, #e6edf3),
24
+ "text-muted": (#656d76, #7d8590),
25
+ "text-secondary": (#656d76, #7d8590),
26
+ "scrollbar": (#d0d7de, #30363d),
27
+ "scrollbar-hover": (#8c959f, #8b949e),
28
+ "code-bg": (#eff1f3, #25292f), // Flat code background
29
+ "code-text": (#1f2328, #e6edf3),
30
+ "highlight": (#fff8c5, #bb800926),
31
+ "table-border": (#d0d7de, #30363d),
32
+ "table-stripe": (#f6f8fa, #161b22)
33
+ ),
34
+ "font": (
35
+ "emoji": "\"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\"",
36
+ "body": "\"Noto Serif\", \"Noto Serif Display\", \"PT Serif\", \"IBM Plex Serif\", \"Literata\", \"Merriweather\", \"Source Serif 4\", \"Georgia\", \"Cambria\", \"Palatino Linotype\", \"Times New Roman\", \"Times\", serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif, var(--font-family-emoji-flag-capable)",
37
+ "mono": "\"ui-monospace\", \"SFMono-Regular\", \"SF Mono\", \"Menlo\", \"Consolas\", \"Liberation Mono\", \"monospace\"",
38
+ "size-base": 16px
39
+ ),
40
+ "layout": (
41
+ "line-height": 1.4,
42
+ "justify-important": start,
43
+ "justify-normal": start,
44
+ "widths": (
45
+ "card": 285px,
46
+ "card-medium": 460px,
47
+ "card-wide": 800px,
48
+ "content": 980px
49
+ )
50
+ ),
51
+ "page": (
52
+ "margin": 2rem
53
+ ),
54
+ "heading": (
55
+ "padding": 0,
56
+ "padding-small": 0
57
+ ),
58
+ "blockquote": (
59
+ "margin-inline": 0,
60
+ "padding-inline": 1em
61
+ ),
62
+ "table": (
63
+ "cell-padding": 6px 13px
64
+ ),
65
+ "media": (
66
+ "img-max-width": 100%
67
+ ),
68
+ "scrollbar": (
69
+ "size": 10px
70
+ )
71
+ );
72
+
73
+ @function md-config($keys...) {
74
+ $value: $md-config;
75
+
76
+ @each $key in $keys {
77
+ @if $value == null {
78
+ @return null;
79
+ }
80
+
81
+ $value: map.get($value, $key);
82
+ }
83
+
84
+ @return $value;
85
+ }
86
+
87
+ @function md-color($name, $mode: null) {
88
+ $palette: md-config("colors");
89
+ $value: map.get($palette, $name);
90
+
91
+ @if $mode == "light" {
92
+ @return if(sass($value != null): list.nth($value, 1));
93
+ }
94
+
95
+ @if $mode == "dark" {
96
+ @return if(sass($value != null): list.nth($value, 2));
97
+ }
98
+
99
+ @return $value;
100
+ }
101
+
102
+ @function md-light-dark($name) {
103
+ $value: md-color($name);
104
+
105
+ @if $value == null {
106
+ @return null;
107
+ }
108
+
109
+ @return light-dark(#{list.nth($value, 1)}, #{list.nth($value, 2)});
110
+ }
@@ -0,0 +1,530 @@
1
+ @use "sass:math";
2
+ @use "sass:color";
3
+ @use "sass:string";
4
+ @use "sass:list";
5
+ @use "sass:map";
6
+
7
+ //
8
+ @mixin make-func($selector) {
9
+ @if (string.slice($selector, 1, 1) == "@") {
10
+ @#{string.slice($selector, 2)} { @content; }
11
+ } @else {
12
+ @#{$selector} { @content; }
13
+ }
14
+ }
15
+
16
+ //
17
+ @function hsv-calc($src-color) {
18
+ // component names (interpretation)
19
+ $h-hsv: h;
20
+ $s-hsv: s;
21
+ $v-hsv: l;
22
+
23
+ // new CSS calc division and conversion into number
24
+ $S_v-frac: calc(#{$s-hsv} / 100);
25
+ $V-frac: calc(#{$v-hsv} / 100);
26
+
27
+ $L-frac: calc(#{$V-frac} * (1 - #{$S_v-frac} / 2));
28
+ $minDen: #{"min"}(#{$L-frac}, calc(1 - #{$L-frac}));
29
+ $safeDen: #{"clamp"}(0.0001, #{$minDen}, 1);
30
+ $S_l-frac: calc((#{$V-frac} - #{$L-frac}) / #{$safeDen});
31
+
32
+ $L-hsl: #{"calc(#{$L-frac} * 100)"};
33
+ $S-hsl: #{"calc(#{$S_l-frac} * 100)"};
34
+
35
+ @return #{"hsl(from #{$src-color} #{$h-hsv} #{$S-hsl} #{$L-hsl} / alpha)"};
36
+ }
37
+
38
+ //
39
+ @function hsv-calc-component($src-cmp) {
40
+ @return hsv-calc(hsl($src-cmp));
41
+ }
42
+
43
+ //
44
+ @include make-func("@function --hsv(--src-color <color>) returns <color>") {
45
+ result: #{hsv-calc(var(--src-color, black))};
46
+ }
47
+
48
+ // or can be just named as `hsv` for SCSS
49
+ @function hsv-calc-wrap($src-color) {
50
+ @return --hsv($src-color);
51
+ }
52
+
53
+ // by syntax, most closer to CSS syntax
54
+ @function hsv($src-cmp) {
55
+ @return hsv-calc-wrap(#{"hsl(#{$src-cmp})"});
56
+ }
57
+
58
+
59
+ // ============================================================================
60
+ // DESIGN SYSTEM CONFIGURATION
61
+ // ============================================================================
62
+ $design-system: (
63
+ "breakpoints": (
64
+ "xs": 320px,
65
+ "sm": 640px,
66
+ "md": 768px,
67
+ "lg": 1024px,
68
+ "xl": 1280px,
69
+ "2xl": 1536px
70
+ ),
71
+ "container-sizes": (
72
+ "xs": 320px,
73
+ "sm": 640px,
74
+ "md": 768px,
75
+ "lg": 1024px,
76
+ "xl": 1280px,
77
+ "2xl": 1536px
78
+ ),
79
+ "spacing": (
80
+ "xs": 0.25rem,
81
+ "sm": 0.5rem,
82
+ "md": 0.75rem,
83
+ "lg": 1rem,
84
+ "xl": 1.25rem,
85
+ "2xl": 1.5rem,
86
+ "3xl": 2rem,
87
+ "4xl": 2.5rem,
88
+ "5xl": 3rem,
89
+ "6xl": 4rem
90
+ ),
91
+ "effects": (
92
+ "active-brightness": 0.95,
93
+ "hover-brightness": 0.96,
94
+ "motion-fast": 140ms cubic-bezier(0.2, 0, 0, 1),
95
+ "motion-normal": 200ms cubic-bezier(0.2, 0, 0, 1),
96
+ "motion-slow": 300ms cubic-bezier(0.2, 0, 0, 1)
97
+ ),
98
+ "shape": (
99
+ "border-radius": (
100
+ "xs": 0.125rem,
101
+ "sm": 0.25rem,
102
+ "md": 0.375rem,
103
+ "lg": 0.5rem,
104
+ "xl": 0.75rem,
105
+ "2xl": 1rem,
106
+ "3xl": 1.5rem,
107
+ "full": 9999px
108
+ ),
109
+ "shadow": (
110
+ "xs": 0 1px 2px 0 rgba(0, 0, 0, 0.05),
111
+ "sm": 0 1px 3px 0 rgba(0, 0, 0, 0.1),
112
+ "md": 0 4px 6px -1px rgba(0, 0, 0, 0.1),
113
+ "lg": 0 10px 15px -3px rgba(0, 0, 0, 0.1),
114
+ "xl": 0 20px 25px -5px rgba(0, 0, 0, 0.1),
115
+ "2xl": 0 25px 50px -12px rgba(0, 0, 0, 0.25),
116
+ "inner": inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)
117
+ )
118
+ ),
119
+ "colors": (
120
+ "primary": (#5a7fff, #7ca7ff),
121
+ "secondary": (#6b7280, #94a3b8),
122
+ "accent": (#64748b, #94a3b8),
123
+ "success": (#10b981, #34d399),
124
+ "warning": (#f59e0b, #fbbf24),
125
+ "error": (#ef4444, #f87171),
126
+ "info": (#60a5fa, #93c5fd),
127
+ "surface": (#fafbfc, #0f1419),
128
+ "surface-container": (#f1f5f9, #1e293b),
129
+ "surface-container-high": (#e2e8f0, #334155),
130
+ "surface-container-low": (#f8fafc, #0f172a),
131
+ "surface-container-highest": (#cbd5e1, #475569),
132
+ "surface-container-lowest": (#fafbfc, #0f1419),
133
+ "border": (#cbd5e1, #475569),
134
+ "border-variant": (#94a3b8, #64748b),
135
+ "border-subtle": (#e2e8f0, #334155),
136
+ "text-primary": (#1e293b, #f1f5f9),
137
+ "text-secondary": (#64748b, #94a3b8),
138
+ "text-muted": (#94a3b8, #64748b),
139
+ "text-disabled": (#cbd5e1, #475569),
140
+ "hover": (#f1f5f9, #334155),
141
+ "active": (#e2e8f0, #1e293b),
142
+ "focus": (#dbeafe, #1e40af),
143
+ "link": (#3b82f6, #60a5fa),
144
+ "code-bg": (#f8fafc, #1e293b),
145
+ "code-text": (#1e293b, #f1f5f9),
146
+ "highlight": (#dbeafe, #1d4ed8),
147
+ "table-border": (#cbd5e1, #475569),
148
+ "table-stripe": (#f8fafc, #1e293b),
149
+ "scrollbar": (#cbd5e1, #64748b),
150
+ "scrollbar-hover": (#94a3b8, #94a3b8),
151
+ "outline": (#cbd5e1, #64748b),
152
+ "outline-variant": (#94a3b8, #cbd5e1)
153
+ ),
154
+ "typography": (
155
+ "font-family": (
156
+ "sans": "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif",
157
+ "mono": "ui-monospace, 'SFMono-Regular', 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace",
158
+ "emoji": "'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'"
159
+ ),
160
+ "font-size": (
161
+ "xs": 0.75rem,
162
+ "sm": 0.875rem,
163
+ "base": 1rem,
164
+ "lg": 1.125rem,
165
+ "xl": 1.25rem,
166
+ "2xl": 1.5rem,
167
+ "3xl": 1.875rem,
168
+ "4xl": 2.25rem,
169
+ "5xl": 3rem,
170
+ "6xl": 3.75rem
171
+ ),
172
+ "font-weight": (
173
+ "thin": 100,
174
+ "light": 300,
175
+ "normal": 400,
176
+ "medium": 500,
177
+ "semibold": 600,
178
+ "bold": 700,
179
+ "extrabold": 800,
180
+ "black": 900
181
+ ),
182
+ "line-height": (
183
+ "tight": 1.25,
184
+ "snug": 1.375,
185
+ "normal": 1.5,
186
+ "relaxed": 1.625,
187
+ "loose": 2
188
+ ),
189
+ "letter-spacing": (
190
+ "tighter": -0.05em,
191
+ "tight": -0.025em,
192
+ "normal": 0,
193
+ "wide": 0.025em,
194
+ "wider": 0.05em,
195
+ "widest": 0.1em
196
+ )
197
+ ),
198
+ "layout": (
199
+ "line-height": 1.4,
200
+ "justify-important": start,
201
+ "justify-normal": start,
202
+ "widths": (
203
+ "card": 285px,
204
+ "card-medium": 460px,
205
+ "card-wide": 800px,
206
+ "content": 980px
207
+ )
208
+ ),
209
+ "page": (
210
+ "margin": 2rem
211
+ ),
212
+ "heading": (
213
+ "padding": 0,
214
+ "padding-small": 0
215
+ ),
216
+ "blockquote": (
217
+ "margin-inline": 0,
218
+ "padding-inline": 1em
219
+ ),
220
+ "table": (
221
+ "cell-padding": 6px 13px
222
+ ),
223
+ "media": (
224
+ "img-max-width": 100%
225
+ ),
226
+ "scrollbar": (
227
+ "size": 10px
228
+ )
229
+ );
230
+
231
+ // ============================================================================
232
+ // TOKENS
233
+ // ============================================================================
234
+ $-z-layers: (
235
+ "base": 0,
236
+ "dropdown": 100,
237
+ "sticky": 200,
238
+ "fixed": 300,
239
+ "modal-backdrop": 400,
240
+ "modal": 500,
241
+ "popover": 600,
242
+ "tooltip": 700,
243
+ "toast": 800,
244
+ "max": 9999
245
+ );
246
+
247
+ // ============================================================================
248
+ // UTILITY FUNCTIONS
249
+ // ============================================================================
250
+ @function config($keys...) {
251
+ $value: $design-system;
252
+
253
+ @each $key in $keys {
254
+ @if $value == null {
255
+ @return null;
256
+ }
257
+
258
+ $value: map.get($value, $key);
259
+ }
260
+
261
+ @return $value;
262
+ }
263
+
264
+ @function theme-color($name, $mode: null) {
265
+ $palette: config("colors");
266
+ $value: map.get($palette, $name);
267
+
268
+ @if $mode == "light" {
269
+ @return if(sass($value != null): list.nth($value, 1); else: null)
270
+ }
271
+
272
+ @if $mode == "dark" {
273
+ @return if(sass($value != null): list.nth($value, 2); else: null)
274
+ }
275
+
276
+ @return $value;
277
+ }
278
+
279
+ @function light-dark($name) {
280
+ $value: theme-color($name);
281
+
282
+ @if $value == null {
283
+ @return null;
284
+ }
285
+
286
+ @return light-dark(#{list.nth($value, 1)}, #{list.nth($value, 2)});
287
+ }
288
+
289
+ @function spacing($size) {
290
+ @return config("spacing", $size);
291
+ }
292
+
293
+ @function breakpoint($name) {
294
+ @return config("breakpoints", $name);
295
+ }
296
+
297
+ @function container-size($name) {
298
+ @return config("container-sizes", $name);
299
+ }
300
+
301
+ @function typography($category, $key) {
302
+ @return config("typography", $category, $key);
303
+ }
304
+
305
+ @function shadow($size) {
306
+ @return config("shape", "shadow", $size);
307
+ }
308
+
309
+ @function radius($size) {
310
+ @return config("shape", "border-radius", $size);
311
+ }
312
+
313
+ //
314
+ $cps: 0.0001;
315
+
316
+ @function mix($a, $b, $i) { @return string.unquote("calc(#{$b} * #{$i} + #{$a} * calc(1 - #{$i}))"); }
317
+ @function abs($a) { @return string.unquote("abs(#{$a})"); }
318
+ @function sign($a) { @return string.unquote("sign(#{$a})"); }
319
+ @function land($a, $b) { @return string.unquote("calc(#{$a} * #{$b})"); }
320
+ @function lor($a, $b) { @return string.unquote("max(#{$a}, #{$b})"); }
321
+
322
+ //
323
+ @function inv-mul($a, $b) {
324
+ @return string.unquote("calc(1.0 - calc(1.0 - #{$a}) * #{$b})");
325
+ }
326
+
327
+ //
328
+ @function gt($a, $b) {
329
+ $diff: "calc(#{$b} - #{$cps} - #{$a})";
330
+ @return string.unquote("max(#{sign($diff)}, 0)");
331
+ }
332
+
333
+ //
334
+ @function lt($a, $b) {
335
+ $diff: "calc(#{$a} - #{$cps} - #{$b})";
336
+ @return string.unquote("max(#{sign($diff)}, 0)");
337
+ }
338
+
339
+ //
340
+ @function ge($a, $b) {
341
+ $diff: "calc(#{$b} + #{$cps} - #{$a})";
342
+ @return string.unquote("max(#{sign($diff)}, 0)");
343
+ }
344
+
345
+ //
346
+ @function le($a, $b) {
347
+ $diff: "calc(#{$a} + #{$cps} - #{$b})";
348
+ @return string.unquote("max(#{sign($diff)}, 0)");
349
+ }
350
+
351
+ //
352
+ @function ne($a, $b) {
353
+ $comp: "calc(#{$a} - #{$b})";
354
+ $diff: "max(#{abs($comp)} - #{$cps}, 0)";
355
+ @return string.unquote("max(#{sign($diff)}, 0)");
356
+ }
357
+
358
+ //
359
+ @function eq($a, $b) {
360
+ $diff: "calc(1 - #{ne($a, $b)})";
361
+ @return string.unquote("max(#{sign($diff)}, 0)");
362
+ }
363
+
364
+
365
+ // ============================================================================
366
+ // UNIT CONVERSION FUNCTIONS
367
+ // ============================================================================
368
+ @function rem($px, $base: 16) {
369
+ @if type-of($px) == "number" and unit($px) == "px" {
370
+ @return math.div($px, $base * 1px) * 1rem;
371
+ } @else if type-of($px) == "number" and unitless($px) {
372
+ @return math.div($px, $base) * 1rem;
373
+ }
374
+
375
+ @return $px;
376
+ }
377
+
378
+ @function em($px, $base: 16) {
379
+ @if type-of($px) == "number" and unit($px) == "px" {
380
+ @return math.div($px, $base * 1px) * 1em;
381
+ } @else if type-of($px) == "number" and unitless($px) {
382
+ @return math.div($px, $base) * 1em;
383
+ }
384
+
385
+ @return $px;
386
+ }
387
+
388
+ // ============================================================================
389
+ // COLOR FUNCTIONS
390
+ // ============================================================================
391
+ @function alpha($color, $opacity) {
392
+ @return color.change($color, $alpha: $opacity);
393
+ }
394
+
395
+ @function lighten-color($color, $amount) {
396
+ @return color.scale($color, $lightness: $amount);
397
+ }
398
+
399
+ @function darken-color($color, $amount) {
400
+ @return color.scale($color, $lightness: - $amount);
401
+ }
402
+
403
+ @function contrast-text($bg) {
404
+ $luminance: color.channel($bg, "lightness", $space: hsl);
405
+ @return if(sass($luminance > 50%): #1a1a1a; else: #ffffff);
406
+ }
407
+
408
+ @function mix-colors($color1, $color2, $weight: 50%) {
409
+ @return color.mix($color1, $color2, $weight);
410
+ }
411
+
412
+ // ============================================================================
413
+ // SPACING FUNCTIONS
414
+ // ============================================================================
415
+ @function space($multiplier, $base: 0.25rem) {
416
+ @return $multiplier * $base;
417
+ }
418
+
419
+ @function negative($value) {
420
+ @return -$value;
421
+ }
422
+
423
+ // ============================================================================
424
+ // Z-INDEX FUNCTIONS
425
+ // ============================================================================
426
+ @function z($layer) {
427
+ @if map.has-key($-z-layers, $layer) {
428
+ @return map.get($-z-layers, $layer);
429
+ }
430
+
431
+ @warn "Unknown z-layer: #{$layer}";
432
+ @return 0;
433
+ }
434
+
435
+ // ============================================================================
436
+ // STRING FUNCTIONS
437
+ // ============================================================================
438
+ @function strip-unit($value) {
439
+ @if type-of($value) == "number" and not unitless($value) {
440
+ @return math.div($value, $value * 0 + 1);
441
+ }
442
+
443
+ @return $value;
444
+ }
445
+
446
+ @function to-class($str) {
447
+ @return string.to-lower-case(string.unquote($str));
448
+ }
449
+
450
+ // ============================================================================
451
+ // LIST/MAP FUNCTIONS
452
+ // ============================================================================
453
+ @function get($map, $key, $fallback: null) {
454
+ @if map.has-key($map, $key) {
455
+ @return map.get($map, $key);
456
+ }
457
+
458
+ @return $fallback;
459
+ }
460
+
461
+ @function deep-get($map, $keys...) {
462
+ @each $key in $keys {
463
+ @if type-of($map) != "map" {
464
+ @return null;
465
+ }
466
+
467
+ $map: map.get($map, $key);
468
+ }
469
+
470
+ @return $map;
471
+ }
472
+
473
+ // ============================================================================
474
+ // MATH FUNCTIONS
475
+ // ============================================================================
476
+ @function clamp-value($value, $min, $max) {
477
+ @return math.max($min, math.min($value, $max));
478
+ }
479
+
480
+ @function percentage($part, $whole) {
481
+ @if $whole == 0 {
482
+ @return 0%;
483
+ }
484
+
485
+ @return math.percentage(math.div($part, $whole));
486
+ }
487
+
488
+ @function round-to($value, $places: 2) {
489
+ $factor: math.pow(10, $places);
490
+ @return math.div(math.round($value * $factor), $factor);
491
+ }
492
+
493
+ //
494
+ @function option-or($options, $key, $fallback) {
495
+ $value: map.get($options, $key);
496
+ @return if(sass($value == null): $fallback; else: $value);
497
+ }
498
+
499
+ // alias for option-or
500
+ @function _option-or($options, $key, $fallback) {
501
+ $value: map.get($options, $key);
502
+ @return if(sass($value == null): $fallback; else: $value);
503
+ }
504
+
505
+ //
506
+ // Fetch function
507
+ @function md3-fetch($source, $token, $label: "token") {
508
+ @if map.has-key($source, $token) {
509
+ @return map.get($source, $token);
510
+ }
511
+
512
+ @error "Unknown #{$label} `#{$token}`. Available: #{map.keys($source)}";
513
+ }
514
+
515
+ //
516
+ @function css-mod($value, $mod) {
517
+ @return string.unquote("mod(#{$value}, #{$mod})");
518
+ }
519
+
520
+ @function css-rem($value, $mod) {
521
+ @return string.unquote("rem(#{$value}, #{$mod})");
522
+ }
523
+
524
+ @function neutral-size($value) {
525
+ @return string.unquote("calc(#{$value} + #{$value})");
526
+ }
527
+
528
+ @function value-or($value, $fallback) {
529
+ @return if(sass($value == null): $fallback; else: $value);
530
+ }