@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,1040 @@
1
+ @use "sass:list";
2
+ @use "sass:map";
3
+ @use "sass:math";
4
+ @use "sass:meta";
5
+ @use "sass:string";
6
+
7
+ // Layout mixins - veela-independent fallbacks
8
+
9
+ @mixin flex-layout($direction: row, $wrap: nowrap, $gap: null) {
10
+ display: flex;
11
+ flex-direction: $direction;
12
+ flex-wrap: $wrap;
13
+ @if $gap { gap: $gap; }
14
+ }
15
+
16
+ @mixin grid-layout($columns: 1fr, $rows: auto, $gap: null) {
17
+ display: grid;
18
+ grid-template-columns: $columns;
19
+ grid-template-rows: $rows;
20
+ @if $gap { gap: $gap; }
21
+ }
22
+
23
+ @mixin center-content {
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ }
28
+
29
+ // =============================================================================
30
+ // LAYOUT & BREAKPOINTS
31
+ // =============================================================================
32
+
33
+
34
+
35
+ //
36
+ // Space scale
37
+ $md3-space-scale: (
38
+ 2xs: clamp(0.1875rem, 0.4cqi + 0.05rem, 0.25rem),
39
+ xs: clamp(0.25rem, 0.45cqi + 0.06rem, 0.5rem),
40
+ sm: clamp(0.5rem, 0.6cqi + 0.1rem, 0.75rem),
41
+ md: clamp(0.75rem, 0.8cqi + 0.18rem, 1rem),
42
+ lg: clamp(1rem, 1cqi + 0.24rem, 1.5rem),
43
+ xl: clamp(1.5rem, 1.4cqi + 0.32rem, 2rem),
44
+ 2xl: clamp(2rem, 2cqi + 0.4rem, 2.75rem),
45
+ 3xl: clamp(2.75rem, 2.6cqi + 0.6rem, 3.5rem),
46
+ 4xl: clamp(3.5rem, 3cqi + 0.8rem, 4.5rem),
47
+ );
48
+
49
+ //
50
+ // Radius scale
51
+ $md3-radius-scale: (
52
+ xs: clamp(0.25rem, 0.6cqi, 0.375rem), // 4-6px
53
+ sm: clamp(0.5rem, 0.8cqi, 0.75rem), // 8-12px
54
+ md: clamp(0.75rem, 1cqi, 1rem), // 12-16px
55
+ lg: clamp(1rem, 1.25cqi, 1.5rem), // 16-24px
56
+ xl: clamp(1.5rem, 1.75cqi, 2rem), // 24-32px
57
+ full: 9999px,
58
+ );
59
+
60
+ //
61
+ // Shape scale
62
+ $md3-shape-scale: (
63
+ corner-none: 0,
64
+ extra-small: clamp(0.25rem, 0.6cqi, 0.375rem),
65
+ extra-small-top: clamp(0.25rem, 0.6cqi, 0.375rem) clamp(0.25rem, 0.6cqi, 0.375rem) 0 0,
66
+ small: clamp(0.5rem, 0.9cqi, 0.75rem),
67
+ small-top: clamp(0.5rem, 0.9cqi, 0.75rem) clamp(0.5rem, 0.9cqi, 0.75rem) 0 0,
68
+ medium: clamp(0.75rem, 1.2cqi, 1rem),
69
+ large: clamp(1rem, 1.5cqi, 1.5rem),
70
+ large-top: clamp(1rem, 1.5cqi, 1.5rem) clamp(1rem, 1.5cqi, 1.5rem) 0 0,
71
+ large-end: clamp(1rem, 1.5cqi, 1.5rem) clamp(1rem, 1.5cqi, 1.5rem) 0 0,
72
+ extra-extra-large: clamp(2rem, 2.4cqi, 2.5rem),
73
+ extra-large: clamp(1.75rem, 2.4cqi, 2.25rem),
74
+ extra-large-top: clamp(1.75rem, 2.4cqi, 2.25rem) clamp(1.75rem, 2.4cqi, 2.25rem) 0 0,
75
+ extra-large-bottom: 0 0 clamp(1.75rem, 2.4cqi, 2.25rem) clamp(1.75rem, 2.4cqi, 2.25rem),
76
+ full: 9999px,
77
+ );
78
+
79
+ //
80
+ // Radius aliases
81
+ $md3-radius-aliases: (
82
+ 3xs: xs,
83
+ 2xs: xs,
84
+ xs: xs,
85
+ extra-small: xs,
86
+ sm: sm,
87
+ small: sm,
88
+ md: md,
89
+ medium: md,
90
+ lg: lg,
91
+ large: lg,
92
+ xl: xl,
93
+ extra-large: xl,
94
+ 2xl: xl,
95
+ 3xl: xl,
96
+ 4xl: xl,
97
+ full: full,
98
+ );
99
+
100
+ //
101
+ // Shape aliases
102
+ $md3-shape-aliases: (
103
+ 3xs: extra-small,
104
+ 2xs: extra-small,
105
+ xs: extra-small,
106
+ extra-small: extra-small,
107
+ sm: small,
108
+ small: small,
109
+ md: medium,
110
+ medium: medium,
111
+ lg: large,
112
+ large: large,
113
+ xl: extra-large,
114
+ extra-large: extra-large,
115
+ 2xl: extra-large,
116
+ 3xl: extra-extra-large,
117
+ 4xl: extra-extra-large,
118
+ full: full,
119
+ );
120
+
121
+ //
122
+ // Breakpoint scale
123
+ $md3-breakpoints: (
124
+ sm: 40rem,
125
+ md: 60rem,
126
+ lg: 75rem,
127
+ xl: 90rem,
128
+ 2xl: 105rem,
129
+ );
130
+
131
+ //
132
+ // Container query thresholds
133
+ $md3-container-compact-max: 30rem;
134
+ $md3-container-cozy-max: 60rem;
135
+
136
+
137
+ //
138
+ // Icon sizes
139
+ $md3-icon-sizes: (
140
+ xs: clamp(0.75rem, 0.35cqi + 0.65rem, 0.9rem),
141
+ sm: clamp(0.95rem, 0.4cqi + 0.85rem, 1.1rem),
142
+ md: clamp(1.25rem, 0.45cqi + 1.1rem, 1.45rem),
143
+ lg: clamp(1.5rem, 0.6cqi + 1.3rem, 1.75rem),
144
+ xl: clamp(2rem, 0.8cqi + 1.65rem, 2.25rem),
145
+ 2xl: clamp(2.5rem, 1cqi + 2.25rem, 3rem),
146
+ 18xs: extra-small,
147
+ 19xs: extra-small,
148
+ 20xs: extra-small,
149
+ 21xs: extra-small,
150
+ 22xs: extra-small,
151
+ 23xs: extra-small,
152
+ 24xs: extra-small,
153
+ 25xs: extra-small,
154
+ 26xs: extra-small,
155
+ 27xs: extra-small,
156
+ 28xs: extra-small,
157
+ 29xs: extra-small,
158
+ 30xs: extra-small,
159
+ 31xs: extra-small,
160
+ full: full,
161
+ );
162
+
163
+ //
164
+ // Avatar sizes
165
+ $md3-avatar-sizes: (
166
+ sm: clamp(2.25rem, 1cqi + 2rem, 2.75rem),
167
+ md: clamp(2.75rem, 1.4cqi + 2.4rem, 3.5rem),
168
+ lg: clamp(3.5rem, 1.6cqi + 3rem, 4.5rem),
169
+ );
170
+
171
+
172
+ //
173
+ // Mobile width
174
+ $mobile-width: 9in;
175
+
176
+ //
177
+ // Is touch
178
+ $is-touch: "screen and (hover: none) and (pointer: coarse)";
179
+ $is-not-wide: "(width < #{$mobile-width})";
180
+ $is-desktop: "(width >= #{$mobile-width})";
181
+ $is-deskinset-block-start: "(((hover: hover) or (pointer: fine)) and ((width >= #{$mobile-width}) or (orientation: landscape)))";
182
+ $is-mobile: "not #{$is-desktop}";
183
+ $is-windowed: "@container u2-windowed #{$is-not-wide}";
184
+
185
+ // Display mixins - veela-independent fallbacks
186
+
187
+ @mixin hidden {
188
+ display: none !important;
189
+ }
190
+
191
+ @mixin visible($type: block) {
192
+ display: #{$type} !important;
193
+ }
194
+
195
+
196
+ //
197
+ @mixin host-related($host, $child) {
198
+ // outside web component
199
+ #{$host} { & > #{$child} { @content; } }
200
+ // inside web component
201
+ :host(#{$host}) { ::slotted(#{$child}) { @content; } }
202
+ }
203
+
204
+ //
205
+ @mixin host-context($host) {
206
+ // outside web component
207
+ #{$host} { @content; }
208
+ // inside web component
209
+ :host(#{$host}) { @content; }
210
+ }
211
+
212
+
213
+ // Spacing helpers
214
+ @mixin padding($value: null) {
215
+ & {
216
+ @if $value != null { --p: #{$value}; }
217
+ padding: var(--p, var(--padding-md, 0.25rem));
218
+ }
219
+ }
220
+
221
+ //
222
+ @mixin margin($value: null) {
223
+ & {
224
+ @if $value != null { --m: #{$value}; }
225
+ margin: var(--m, var(--space-md, 0rem));
226
+ }
227
+ }
228
+
229
+ //
230
+ @mixin spacing($p: null, $m: null) {
231
+ & {
232
+ @if $p != null { padding: $p; }
233
+ @if $m != null { margin: $m; }
234
+ }
235
+ }
236
+
237
+ // Border/radius/shadow helpers
238
+ @mixin border($inline-size: null, $style: null, $color: null) {
239
+ & {
240
+ @if $width != null { --border-w: #{$width}; }
241
+ @if $style != null { --border-s: #{$style}; }
242
+ @if $color != null { --border-c: #{$color}; }
243
+ border-width: var(--border-w, 0.5px);
244
+ border-style: var(--border-s, solid);
245
+ border-color: var(--border-c, currentColor);
246
+ }
247
+ }
248
+
249
+ // Alignment helpers
250
+ @mixin center($axis: "both") {
251
+ & {
252
+ @if $axis == "both" { place-content: center; place-items: center; }
253
+ @else if $axis == "x" { justify-content: center; align-items: stretch; }
254
+ @else if $axis == "y" { align-items: center; justify-content: stretch; }
255
+ }
256
+ }
257
+
258
+
259
+ // Border/radius/shadow helpers
260
+ @mixin outline($inline-size: null, $style: null, $color: null) {
261
+ & {
262
+ @if $width != null { --outline-w: #{$width}; }
263
+ @if $style != null { --outline-s: #{$style}; }
264
+ @if $color != null { --outline-c: #{$color}; }
265
+ outline-width: var(--outline-w, 0.5px);
266
+ outline-style: var(--outline-s, solid);
267
+ outline-color: var(--outline-c, currentColor);
268
+ }
269
+ }
270
+
271
+ //
272
+ @mixin radius($r: null) { & { @if $r != null { --radius: #{$r}; } border-radius: var(--radius, var(--radius-md, 0.25rem)); } }
273
+ @mixin border-radius($r: null) { & { @if $r != null { --radius: #{$r}; } border-radius: var(--radius, var(--radius-md, 0.25rem)); } }
274
+ @mixin shadow($value: null) { & { @if $value != null { --shadow: #{$value}; } box-shadow: var(--shadow); } }
275
+
276
+ // Container helpers
277
+ // pseudo-container helper for future compatibility
278
+
279
+ @mixin box($r: null, $ov: null) {
280
+ & {
281
+ @if $r != null { --radius: #{$r}; }
282
+ @if $ov != null { --overflow: #{$ov}; }
283
+ border-radius: var(--radius, var(--radius-md, 0.25rem));
284
+ overflow: var(--overflow, visible);
285
+ }
286
+ }
287
+
288
+ @mixin color($bg: null, $color: null) {
289
+ & {
290
+ @if $bg != null { --bg: #{$bg}; }
291
+ @if $color != null { --fg: #{$color}; }
292
+ color: var(--fg, currentColor);
293
+ background-color: var(--bg, transparent);
294
+ }
295
+ }
296
+
297
+
298
+
299
+
300
+
301
+ @mixin flex-center {
302
+ display: flex;
303
+ align-items: center;
304
+ justify-content: center;
305
+ }
306
+
307
+ @mixin flex-between {
308
+ display: flex;
309
+ align-items: center;
310
+ justify-content: space-between;
311
+ }
312
+
313
+ // Size mixins - veela-independent fallbacks
314
+
315
+
316
+ @mixin min-size($inline: null, $block: null) {
317
+ @if $inline { min-inline-size: $inline; }
318
+ @if $block { min-block-size: $block; }
319
+ }
320
+
321
+ @mixin max-size($inline: null, $block: null) {
322
+ @if $inline { max-inline-size: $inline; }
323
+ @if $block { max-block-size: $block; }
324
+ }
325
+
326
+ @mixin full-size {
327
+ inline-size: 100%;
328
+ block-size: 100%;
329
+ }
330
+
331
+ // Sizing
332
+ @mixin size($inline: null, $block: null, $aspect: null) {
333
+ & {
334
+ @if $inline == 100% and $block == 100% {
335
+ inline-size: 100%;
336
+ block-size: 100%;
337
+ } @else {
338
+ @if $inline { inline-size: $inline; }
339
+ @if $block { block-size: $block; }
340
+ }
341
+ @if $aspect { aspect-ratio: $aspect; }
342
+ @if $inline != null { --i-size: #{$inline}; }
343
+ @if $block != null { --b-size: #{$block}; }
344
+ @if $aspect != null { --ar: #{$aspect}; }
345
+ inline-size: var(--i-size, 100%);
346
+ block-size: var(--b-size, 100%);
347
+ aspect-ratio: var(--ar, auto);
348
+ }
349
+ }
350
+
351
+ @mixin position($type: null, $inset: null) {
352
+ & {
353
+ @if $type != null { --pos: #{$type}; }
354
+ @if $inset != null { --inset: #{$inset}; }
355
+ position: var(--pos, absolute);
356
+ inset: var(--inset, 0);
357
+ }
358
+ }
359
+
360
+ @mixin display-2($type: 'block', $align: null, $justify: null) {
361
+ @if $type == 'flex' or $type == 'inline-flex' {
362
+ display: #{$type};
363
+ @if $align { align-items: $align; }
364
+ @if $justify { justify-content: $justify; }
365
+ } @else if $type == 'grid' or $type == 'inline-grid' {
366
+ display: #{$type};
367
+ @if $align { align-items: $align; }
368
+ @if $justify { justify-items: $justify; }
369
+ } @else if $type == 'none' {
370
+ display: none;
371
+ } @else {
372
+ display: #{$type};
373
+ }
374
+ }
375
+
376
+ @mixin display($type: null, $direction: null, $items: null, $content: null) {
377
+ & {
378
+ @if $type != null { --display: #{$type}; }
379
+ @if $direction != null { --flow: #{$direction}; }
380
+ @if $items != null { --items: #{$items}; }
381
+ @if $content != null { --content: #{$content}; }
382
+ display: var(--display, inline-block);
383
+ flex-direction: var(--flow, row);
384
+ place-items: var(--items, center);
385
+ place-content: var(--content, center);
386
+ box-sizing: border-box;
387
+ }
388
+ }
389
+
390
+ @mixin interaction($pointerEvents: null, $cursor: null, $userSelect: null) {
391
+ & {
392
+ @if $pointerEvents != null { --pe: #{$pointerEvents}; }
393
+ @if $userSelect != null { --us: #{$userSelect}; }
394
+ @if $cursor != null { --cursor: #{$cursor}; }
395
+ pointer-events: var(--pe, auto);
396
+ user-select: var(--us, none);
397
+ }
398
+ }
399
+
400
+ @mixin scrollbar($overflow: null, $inline-size: null, $color: null, $gutter: null) {
401
+ & {
402
+ @if $width != null { --sb-w: #{$width}; }
403
+ @if $color != null { --sb-c: #{$color}; }
404
+ @if $gutter != null { --sb-g: #{$gutter}; }
405
+ @if $overflow != null { --ov: #{$overflow}; }
406
+ scrollbar-width: var(--sb-w, thin);
407
+ scrollbar-color: var(--sb-c, transparent transparent);
408
+ scrollbar-gutter: var(--sb-g, auto);
409
+ overflow: var(--ov, hidden);
410
+ }
411
+ }
412
+
413
+ @mixin place($method: stretch, $items: center) {
414
+ & { place-content: #{$method}; place-items: #{$items}; }
415
+ }
416
+
417
+ @mixin grid-flow($direction: row) {
418
+ & {
419
+ display: grid;
420
+ grid-auto-flow: #{$direction};
421
+ }
422
+ }
423
+
424
+ @mixin grid-center {
425
+ display: grid;
426
+ place-items: center;
427
+ }
428
+
429
+ @mixin flex-flow($direction: row) {
430
+ & {
431
+ display: flex;
432
+ flex-direction: #{$direction};
433
+ }
434
+ }
435
+
436
+ @mixin grid-column {
437
+ @include grid-flow(row);
438
+ @include place(center);
439
+
440
+ & {
441
+ --order: sibling-index();
442
+ grid-column: var(--order, 1) / calc(var(--order, 1) + 1);
443
+ grid-row: 1 / -1;
444
+ grid-template-columns: minmax(0px, 1fr);
445
+ grid-template-rows: subgrid;
446
+ }
447
+ }
448
+
449
+ @mixin grid-row {
450
+ @include grid-flow(column);
451
+ @include place(center);
452
+
453
+ & {
454
+ --order: sibling-index();
455
+ grid-column: 1 / -1;
456
+ grid-row: var(--order, 1) / calc(var(--order, 1) + 1);
457
+ grid-template-columns: subgrid;
458
+ grid-template-rows: minmax(0px, max-content);
459
+ }
460
+ }
461
+
462
+ @mixin flex-column {
463
+ & {
464
+ --order: sibling-index();
465
+ order: var(--order, auto);
466
+ flex: 1 1 max-content;
467
+ }
468
+
469
+ @include place(center);
470
+ }
471
+
472
+ @function limit-by-size($pwidth, $basis: 100%, $min: 0px) {
473
+ @return max(calc($basis - ($basis - $pwidth)), $min);
474
+ }
475
+
476
+ @mixin inline-stretch { & { inline-size: 100%; inline-size: -webkit-fill-available; inline-size: stretch; } }
477
+ @mixin block-stretch { & { block-size: 100%; block-size: -webkit-fill-available; block-size: stretch; } }
478
+ @mixin content-inline-size { & { padding-inline: limit-by-size(calc(var(--content-inline-size, 100%) * 0.5), 100%); } }
479
+ @mixin content-block-size { & { padding-block: limit-by-size(calc(var(--content-block-size, 100%) * 0.5), 100%); } }
480
+ @mixin ux-anchor { & { transform: scale3d(var(--scale, 1), var(--scale, 1), 1) translate3d(var(--translate-x, 0px), var(--translate-y, 0px), 0px); } }
481
+
482
+ @mixin grid-layered {
483
+ & { grid-template-columns: minmax(0px, 1fr); grid-template-rows: minmax(0px, 1fr); }
484
+ & > * { grid-column: 1 / -1; grid-row: 1 / -1; }
485
+ }
486
+
487
+ @mixin grid-rows-3c { & { grid-template-columns: minmax(0px, max-content) minmax(0px, 1fr) minmax(0px, max-content); } }
488
+
489
+ @mixin grid-layout($columns: minmax(0px, 1fr), $rows: minmax(0px, 1fr), $type: inline) {
490
+ display: #{$type} grid;
491
+ grid-template-columns: #{$columns};
492
+ grid-template-rows: #{$rows};
493
+ }
494
+
495
+ @mixin grid-auto-fill($min-size: null) {
496
+ @if $min-size != null { --min-col-size: #{$min-size}; }
497
+ display: grid;
498
+ grid-template-columns: repeat(auto-fill, minmax(var(--min-col-size, 260px), 1fr));
499
+ gap: var(--gap-md);
500
+ }
501
+
502
+ @mixin scrollable($direction: "y") {
503
+ @if $direction == "x" {
504
+ overflow-inline: auto;
505
+ overflow-block: hidden;
506
+ }
507
+
508
+ @else if $direction == "y" {
509
+ overflow-block: auto;
510
+ overflow-inline: hidden;
511
+ }
512
+
513
+ @else {
514
+ overflow-inline: auto;
515
+ overflow-block: auto;
516
+ }
517
+
518
+ scrollbar-width: thin;
519
+ scrollbar-color: oklch(
520
+ from --c2-on-surface(
521
+ var(--scrollbar-tint),
522
+ var(--current, var(--color-on-surface, var(--md-on-surface, #1c1b1f)))
523
+ ) l c h / var(--scrollbar-opacity)
524
+ ) transparent;
525
+ -webkit-overflow-scrolling: touch;
526
+
527
+ &::-webkit-scrollbar {
528
+ inline-size: 6px;
529
+ block-size: 6px;
530
+ }
531
+
532
+ &::-webkit-scrollbar-thumb {
533
+ background-color: oklch(
534
+ from --c2-on-surface(
535
+ var(--scrollbar-tint),
536
+ var(--current, var(--color-on-surface, var(--md-on-surface, #1c1b1f)))
537
+ ) l c h / var(--scrollbar-opacity)
538
+ );
539
+ border-radius: var(--radius-full);
540
+ }
541
+
542
+ &::-webkit-scrollbar-track {
543
+ background-color: transparent;
544
+ }
545
+ }
546
+
547
+ @mixin hide-scrollbar {
548
+ scrollbar-width: none;
549
+
550
+ &::-webkit-scrollbar {
551
+ display: none;
552
+ }
553
+ }
554
+
555
+ @mixin breakpoint($size) {
556
+ $map: (
557
+ "sm": 480px,
558
+ "md": 720px,
559
+ "lg": 960px,
560
+ "xl": 1200px
561
+ );
562
+
563
+ $limit: map.get($map, $size);
564
+
565
+ @if $limit {
566
+ @media (max-inline-size: $limit) { @content; }
567
+ } @else {
568
+ @media (max-inline-size: #{$size}) { @content; }
569
+ }
570
+ }
571
+
572
+ @mixin breakpoint-up($size) {
573
+ $map: (
574
+ "sm": 481px,
575
+ "md": 721px,
576
+ "lg": 961px,
577
+ "xl": 1201px
578
+ );
579
+
580
+ $limit: map.get($map, $size);
581
+
582
+ @if $limit {
583
+ @media (min-inline-size: $limit) { @content; }
584
+ } @else {
585
+ @media (min-inline-size: #{$size}) { @content; }
586
+ }
587
+ }
588
+
589
+ @mixin container-query($size) {
590
+ $map: (
591
+ "sm": 480px,
592
+ "md": 720px,
593
+ "lg": 960px
594
+ );
595
+
596
+ $limit: map.get($map, $size);
597
+
598
+ @if $limit {
599
+ @container (max-inline-size: $limit) { @content; }
600
+ } @else {
601
+ @container (max-inline-size: #{$size}) { @content; }
602
+ }
603
+ }
604
+
605
+ @mixin flex($direction: row, $items: center, $content: center) {
606
+ @include display('flex', $direction, $items, $content);
607
+ }
608
+
609
+ @mixin grid($columns: minmax(0px, 1fr), $rows: minmax(0px, var(--ui-window-frame-titlebar-height)) minmax(0px, 1fr)) {
610
+ display: grid;
611
+ grid-template-columns: #{$columns};
612
+ grid-template-rows: #{$rows};
613
+ grid-column: 1 / -1;
614
+ grid-row: 1 / -1;
615
+ }
616
+
617
+ //
618
+ @mixin container-base($size: stretch, $strict: false, $type: size, $name: auto, $contain: strict) {
619
+ & {
620
+ container-type: $type;
621
+ @if $name != auto { container-name: $name; }
622
+ contain: $contain;
623
+ }
624
+
625
+ @if $strict {
626
+ @include size($size);
627
+ }
628
+ @else {
629
+ @include size(stretch);
630
+ }
631
+ }
632
+
633
+ @mixin container-layout($type: ui-container, $contain: strict) {
634
+ @include container-base(stretch, false, $type, auto, $contain);
635
+ }
636
+
637
+ // Container query variants
638
+ @mixin container($size) {
639
+ max-inline-size: stretch;//$container-max-width;
640
+
641
+ $map: (
642
+ "sm": 480px,
643
+ "md": 720px,
644
+ "lg": 960px
645
+ );
646
+
647
+ $limit: map.get($map, $size);
648
+
649
+ /*@include media-down(md) {
650
+ padding: 0 $spacing-md;
651
+ }*/
652
+
653
+ @if $limit {
654
+ @container (max-inline-size: $limit) { @content; }
655
+ } @else {
656
+ @container (max-inline-size: #{$size}) { @content; }
657
+ }
658
+ }
659
+
660
+
661
+ @mixin text($size: $ui-font-base-size, $weight: 400, $color: currentColor) {
662
+ font-size: #{$size};
663
+ font-weight: #{$weight};
664
+ color: #{$color};
665
+ }
666
+
667
+ @mixin text-ellipsis {
668
+ white-space: nowrap;
669
+ overflow: hidden;
670
+ text-overflow: ellipsis;
671
+ }
672
+
673
+ // =============================================================================
674
+ // RESPONSIVE MIXINS
675
+ // =============================================================================
676
+
677
+ @mixin media-up($breakpoint) {
678
+ @if $breakpoint == sm {
679
+ @media (min-inline-size: $breakpoint-sm) {
680
+ @content;
681
+ }
682
+ } @else if $breakpoint == md {
683
+ @media (min-inline-size: $breakpoint-md) {
684
+ @content;
685
+ }
686
+ } @else if $breakpoint == lg {
687
+ @media (min-inline-size: $breakpoint-lg) {
688
+ @content;
689
+ }
690
+ } @else if $breakpoint == xl {
691
+ @media (min-inline-size: $breakpoint-xl) {
692
+ @content;
693
+ }
694
+ } @else if $breakpoint == 2xl {
695
+ @media (min-inline-size: $breakpoint-2xl) {
696
+ @content;
697
+ }
698
+ }
699
+ }
700
+
701
+ //
702
+ @mixin media-down($breakpoint) {
703
+ @if $breakpoint == sm {
704
+ @media (max-inline-size: #{$breakpoint-sm - 1px}) {
705
+ @content;
706
+ }
707
+ } @else if $breakpoint == md {
708
+ @media (max-inline-size: #{$breakpoint-md - 1px}) {
709
+ @content;
710
+ }
711
+ } @else if $breakpoint == lg {
712
+ @media (max-inline-size: #{$breakpoint-lg - 1px}) {
713
+ @content;
714
+ }
715
+ } @else if $breakpoint == xl {
716
+ @media (max-inline-size: #{$breakpoint-xl - 1px}) {
717
+ @content;
718
+ }
719
+ } @else if $breakpoint == 2xl {
720
+ @media (max-inline-size: #{$breakpoint-2xl - 1px}) {
721
+ @content;
722
+ }
723
+ }
724
+ }
725
+
726
+ @mixin media-between($min, $max) {
727
+ @media (min-inline-size: $min) and (max-inline-size: #{$max - 1px}) {
728
+ @content;
729
+ }
730
+ }
731
+
732
+ // =============================================================================
733
+ // LAYOUT MIXINS
734
+ // =============================================================================
735
+
736
+ @mixin grid-auto-fit($min-inline-size: 250px) {
737
+ display: grid;
738
+ grid-template-columns: repeat(auto-fit, minmax($min-width, 1fr));
739
+ gap: $spacing-lg;
740
+ }
741
+
742
+ // =============================================================================
743
+ // VISUAL EFFECTS MIXINS
744
+ // (moved to design/_effects.scss)
745
+ // =============================================================================
746
+
747
+ // =============================================================================
748
+ // UTILITY MIXINS
749
+ // =============================================================================
750
+
751
+ @mixin sr-only {
752
+ position: absolute;
753
+ inline-size: 1px;
754
+ block-size: 1px;
755
+ padding: 0;
756
+ margin: -1px;
757
+ overflow: hidden;
758
+ clip: rect(0, 0, 0, 0);
759
+ white-space: nowrap;
760
+ border: 0;
761
+ }
762
+
763
+ @mixin truncate {
764
+ overflow: hidden;
765
+ text-overflow: ellipsis;
766
+ white-space: nowrap;
767
+ }
768
+
769
+ @mixin aspect-ratio($width, $height) {
770
+ position: relative;
771
+
772
+ &::before {
773
+ content: "";
774
+ display: block;
775
+ padding-block-start: calc(#{$height} / #{$width} * 100%);
776
+ }
777
+
778
+ & > * {
779
+ position: absolute;
780
+ inset-block-start: 0;
781
+ inset-inline-start: 0;
782
+ inline-size: 100%;
783
+ block-size: 100%;
784
+ }
785
+ }
786
+
787
+
788
+
789
+
790
+
791
+ //
792
+ @mixin fit-content-inline {
793
+ interpolate-size: allow-keywords;
794
+ min-inline-size: min-content;
795
+ max-inline-size: stretch;
796
+ inline-size: fit-content;
797
+ }
798
+
799
+ //
800
+ @mixin fit-content-block {
801
+ interpolate-size: allow-keywords;
802
+ min-block-size: min-content;
803
+ max-block-size: stretch;
804
+ block-size: fit-content;
805
+ }
806
+
807
+ //
808
+ @mixin stretch-inline {
809
+ interpolate-size: allow-keywords;
810
+ max-inline-size: stretch;
811
+ inline-size: stretch;
812
+ }
813
+
814
+ //
815
+ @mixin stretch-block {
816
+ interpolate-size: allow-keywords;
817
+ max-block-size: stretch;
818
+ block-size: stretch;
819
+ }
820
+
821
+ //
822
+ @mixin stretch {
823
+ interpolate-size: allow-keywords;
824
+ max-inline-size: stretch;
825
+ max-block-size: stretch;
826
+ inline-size: stretch;
827
+ block-size: stretch;
828
+ }
829
+
830
+ //
831
+ @mixin container-inline-clamped($inline: max-content) {
832
+ interpolate-size: allow-keywords;
833
+ max-inline-size: stretch;
834
+ inline-size: calc-size($inline, clamp(0px, size, min(100cqi, 100dvi)));
835
+ min-inline-size: min-content;
836
+ }
837
+
838
+ //
839
+ @mixin container-block-clamped($block: max-content) {
840
+ interpolate-size: allow-keywords;
841
+ max-block-size: stretch;
842
+ block-size: calc-size($block, clamp(0px, size, min(100cqb, 100dvb)));
843
+ min-block-size: min-content;
844
+ }
845
+
846
+ //
847
+ @mixin container-clamped($inline: max-content, $block: max-content) {
848
+ interpolate-size: allow-keywords;
849
+ @include container-inline-clamped($inline);
850
+ @include container-block-clamped($block);
851
+ }
852
+
853
+
854
+ // Typography mixins - veela-independent fallbacks
855
+
856
+ @mixin typography-props($size: null, $weight: null, $line-height: null, $family: null) {
857
+ @if $size { font-size: $size; }
858
+ @if $weight { font-weight: $weight; }
859
+ @if $line-height { line-height: $line-height; }
860
+ @if $family { font-family: $family; }
861
+ }
862
+
863
+ @mixin text-wrap($wrap: normal) {
864
+ white-space: $wrap;
865
+ overflow-wrap: break-word;
866
+ word-break: break-word;
867
+ }
868
+
869
+ @mixin heading-level($level: 1) {
870
+ font-weight: var(--fl-font-weight-bold, 700);
871
+ line-height: var(--fl-leading-tight, 1.2);
872
+
873
+ @if $level == 1 {
874
+ font-size: var(--fl-text-4xl, 2.5rem);
875
+ } @else if $level == 2 {
876
+ font-size: var(--fl-text-3xl, 2rem);
877
+ } @else if $level == 3 {
878
+ font-size: var(--fl-text-2xl, 1.6rem);
879
+ } @else if $level == 4 {
880
+ font-size: var(--fl-text-xl, 1.25rem);
881
+ } @else {
882
+ font-size: var(--fl-text-lg, 1rem);
883
+ }
884
+ }
885
+
886
+ // Color mixins - veela-independent fallbacks
887
+ // Uses CSS custom properties for theming compatibility
888
+
889
+ @mixin color($color: null, $bg: null, $border-color: null) {
890
+ @if $color { color: $color; }
891
+ @if $bg { background-color: $bg; }
892
+ @if $border-color { border-color: $border-color; }
893
+ }
894
+
895
+ @mixin surface($tone: 0) {
896
+ // Fallback surface colors using CSS variables
897
+ // Can be overridden by any theming system
898
+ background-color: var(--fl-surface, #fff);
899
+ color: var(--fl-on-surface, #111);
900
+ }
901
+
902
+ @mixin primary-surface {
903
+ background-color: var(--fl-primary, #1a73e8);
904
+ color: var(--fl-on-primary, #fff);
905
+ }
906
+
907
+ @mixin secondary-surface {
908
+ background-color: var(--fl-secondary, #5f6368);
909
+ color: var(--fl-on-secondary, #fff);
910
+ }
911
+
912
+ // Border mixins - veela-independent fallbacks
913
+
914
+ @mixin border($width: 1px, $style: solid, $color: currentColor) {
915
+ border: $width $style $color;
916
+ }
917
+
918
+ @mixin border-radius($radius) {
919
+ border-radius: $radius;
920
+ }
921
+
922
+ @mixin rounded($size: md) {
923
+ @if $size == xs {
924
+ border-radius: var(--fl-radius-xs, 0.25rem);
925
+ } @else if $size == sm {
926
+ border-radius: var(--fl-radius-sm, 0.5rem);
927
+ } @else if $size == md {
928
+ border-radius: var(--fl-radius-md, 0.75rem);
929
+ } @else if $size == lg {
930
+ border-radius: var(--fl-radius-lg, 0.85rem);
931
+ } @else if $size == xl {
932
+ border-radius: var(--fl-radius-xl, 1rem);
933
+ } @else if $size == full {
934
+ border-radius: 9999px;
935
+ } @else {
936
+ border-radius: $size;
937
+ }
938
+ }
939
+
940
+ @mixin no-border {
941
+ border: none;
942
+ border-width: 0;
943
+ }
944
+
945
+ // Interaction mixins - veela-independent fallbacks
946
+
947
+ @mixin interaction($pointerEvents: null, $cursor: null, $userSelect: null) {
948
+ @if $pointerEvents { pointer-events: #{$pointerEvents}; }
949
+ @if $cursor { cursor: #{$cursor}; }
950
+ @if $userSelect { user-select: #{$userSelect}; }
951
+ }
952
+
953
+ @mixin non-interactive {
954
+ pointer-events: none;
955
+ cursor: default;
956
+ user-select: none;
957
+ }
958
+
959
+ @mixin selectable {
960
+ user-select: text;
961
+ cursor: text;
962
+ }
963
+
964
+ @mixin draggable {
965
+ cursor: grab;
966
+ user-select: none;
967
+ touch-action: none;
968
+
969
+ &:active {
970
+ cursor: grabbing;
971
+ }
972
+ }
973
+
974
+ // Shadow mixins - veela-independent fallbacks
975
+
976
+ @mixin shadow($value) {
977
+ box-shadow: #{$value};
978
+ }
979
+
980
+ @mixin elevation($level: 1) {
981
+ @if $level == 0 {
982
+ box-shadow: none;
983
+ } @else if $level == 1 {
984
+ box-shadow: var(--fl-shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
985
+ } @else if $level == 2 {
986
+ box-shadow: var(--fl-shadow-md, 0 4px 6px rgba(0, 0, 0, 0.1));
987
+ } @else if $level == 3 {
988
+ box-shadow: var(--fl-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));
989
+ } @else if $level == 4 {
990
+ box-shadow: var(--fl-shadow-xl, 0 20px 25px rgba(0, 0, 0, 0.1));
991
+ } @else {
992
+ box-shadow: var(--fl-shadow-2xl, 0 25px 50px rgba(0, 0, 0, 0.1));
993
+ }
994
+ }
995
+
996
+ @mixin no-shadow {
997
+ box-shadow: none;
998
+ }
999
+
1000
+ // Container mixins - veela-independent fallbacks
1001
+
1002
+ @mixin container-base($size: auto, $strict: false, $type: size, $name: null, $mode: null) {
1003
+ container-type: $type;
1004
+ @if $name { container-name: $name; }
1005
+
1006
+ @if $strict {
1007
+ contain: strict;
1008
+ } @else {
1009
+ contain: layout paint style;
1010
+ }
1011
+
1012
+ @if $size == stretch {
1013
+ inline-size: stretch;
1014
+ block-size: stretch;
1015
+ } @else if $size != auto {
1016
+ inline-size: $size;
1017
+ block-size: $size;
1018
+ }
1019
+ }
1020
+
1021
+ @mixin container($name: null, $type: inline-size) {
1022
+ container-type: $type;
1023
+ @if $name { container-name: $name; }
1024
+ }
1025
+
1026
+ @mixin container-query-named($name, $min: null, $max: null) {
1027
+ @if $min and $max {
1028
+ @container #{$name} (min-width: #{$min}) and (max-width: #{$max}) {
1029
+ @content;
1030
+ }
1031
+ } @else if $min {
1032
+ @container #{$name} (min-width: #{$min}) {
1033
+ @content;
1034
+ }
1035
+ } @else if $max {
1036
+ @container #{$name} (max-width: #{$max}) {
1037
+ @content;
1038
+ }
1039
+ }
1040
+ }