@mastors/core 1.1.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/LICENSE +21 -0
- package/README.md +940 -0
- package/api/_index.scss +5 -0
- package/dist/mastors-core.css +7419 -0
- package/dist/mastors-core.css.map +1 -0
- package/package.json +73 -0
- package/postinstall.js +41 -0
- package/scripts/generate-tokens.js +259 -0
- package/scss/abstracts/_index.scss +6 -0
- package/scss/abstracts/_maps.scss +9 -0
- package/scss/abstracts/_placeholders.scss +7 -0
- package/scss/accessibility/_focus.scss +21 -0
- package/scss/accessibility/_index.scss +7 -0
- package/scss/accessibility/_motion.scss +14 -0
- package/scss/accessibility/_print.scss +52 -0
- package/scss/accessibility/_screen-reader.scss +31 -0
- package/scss/api/_index.scss +14 -0
- package/scss/base/_box-sizing.scss +6 -0
- package/scss/base/_index.scss +7 -0
- package/scss/base/_reset.scss +59 -0
- package/scss/base/_root.scss +43 -0
- package/scss/base/_typography-base.scss +40 -0
- package/scss/config/_flags.scss +13 -0
- package/scss/config/_index.scss +12 -0
- package/scss/config/_settings.scss +18 -0
- package/scss/functions/_color.scss +66 -0
- package/scss/functions/_em.scss +28 -0
- package/scss/functions/_index.scss +15 -0
- package/scss/functions/_map-helpers.scss +29 -0
- package/scss/functions/_math.scss +40 -0
- package/scss/functions/_rem.scss +27 -0
- package/scss/functions/_string.scss +57 -0
- package/scss/functions/_vars.scss +49 -0
- package/scss/generators/_class-generator.scss +83 -0
- package/scss/generators/_custom-property-generator.scss +29 -0
- package/scss/generators/_index.scss +6 -0
- package/scss/generators/_responsive-generator.scss +28 -0
- package/scss/helpers/_clearfix.scss +9 -0
- package/scss/helpers/_index.scss +7 -0
- package/scss/helpers/_ratio.scss +22 -0
- package/scss/helpers/_truncate.scss +25 -0
- package/scss/helpers/_visually-hidden.scss +39 -0
- package/scss/index.scss +41 -0
- package/scss/mixins/_breakpoint.scss +33 -0
- package/scss/mixins/_container.scss +20 -0
- package/scss/mixins/_elevation.scss +12 -0
- package/scss/mixins/_index.scss +9 -0
- package/scss/mixins/_pseudo.scss +13 -0
- package/scss/mixins/_theme.scss +31 -0
- package/scss/mixins/_transition.scss +20 -0
- package/scss/responsive/_container-queries.scss +31 -0
- package/scss/responsive/_engine.scss +65 -0
- package/scss/responsive/_fluid-type.scss +40 -0
- package/scss/responsive/_index.scss +6 -0
- package/scss/semantic/_colors.scss +29 -0
- package/scss/semantic/_index.scss +6 -0
- package/scss/semantic/_spacing.scss +13 -0
- package/scss/semantic/_typography.scss +13 -0
- package/scss/themes/_base-theme.scss +28 -0
- package/scss/themes/_dark.scss +59 -0
- package/scss/themes/_index.scss +6 -0
- package/scss/themes/_light.scss +31 -0
- package/scss/tokens/_color.scss +100 -0
- package/scss/tokens/_index.scss +12 -0
- package/scss/tokens/_opacity.scss +28 -0
- package/scss/tokens/_radii.scss +21 -0
- package/scss/tokens/_shadows.scss +20 -0
- package/scss/tokens/_sizing.scss +47 -0
- package/scss/tokens/_spacing.scss +48 -0
- package/scss/tokens/_transitions.scss +27 -0
- package/scss/tokens/_typography.scss +63 -0
- package/scss/tokens/_z-index.scss +21 -0
- package/scss/utilities/_animation.scss +125 -0
- package/scss/utilities/_borders.scss +55 -0
- package/scss/utilities/_colors.scss +42 -0
- package/scss/utilities/_cursor.scss +28 -0
- package/scss/utilities/_display.scss +26 -0
- package/scss/utilities/_index.scss +20 -0
- package/scss/utilities/_interaction.scss +156 -0
- package/scss/utilities/_layout.scss +162 -0
- package/scss/utilities/_opacity.scss +9 -0
- package/scss/utilities/_overflow.scss +36 -0
- package/scss/utilities/_pointer-events.scss +6 -0
- package/scss/utilities/_position.scss +32 -0
- package/scss/utilities/_shadows.scss +11 -0
- package/scss/utilities/_sizing.scss +40 -0
- package/scss/utilities/_spacing.scss +42 -0
- package/scss/utilities/_transform.scss +43 -0
- package/scss/utilities/_typography.scss +163 -0
- package/scss/utilities/_z-index.scss +9 -0
- package/scss/variables/_breakpoints.scss +14 -0
- package/scss/variables/_container.scss +13 -0
- package/scss/variables/_global.scss +8 -0
- package/scss/variables/_grid.scss +7 -0
- package/scss/variables/_index.scss +7 -0
- package/scss/vendors/_index.scss +15 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// functions/_vars.scss
|
|
2
|
+
// vars() — reference any design token as a CSS custom property by name.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
// All Mastors tokens are emitted as --mastors-{name} custom properties
|
|
5
|
+
// by the token layer. This function wraps that convention so downstream
|
|
6
|
+
// consumers never have to hard-code the --mastors- prefix themselves,
|
|
7
|
+
// and so token references remain refactor-safe if the prefix ever changes.
|
|
8
|
+
// Usage:
|
|
9
|
+
// color: vars(accent); → var(--mastors-accent)
|
|
10
|
+
// background-color: vars(surface-raised); → var(--mastors-surface-raised)
|
|
11
|
+
// box-shadow: vars(shadow-lg); → var(--mastors-shadow-lg)
|
|
12
|
+
// With a CSS fallback (passed through verbatim):
|
|
13
|
+
// color: vars(accent, #3b82f6); → var(--mastors-accent, #3b82f6)
|
|
14
|
+
// gap: vars(spacing-4, 1rem); → var(--mastors-spacing-4, 1rem)
|
|
15
|
+
// Composing with other functions is fine — Sass evaluates eagerly:
|
|
16
|
+
// transition: opacity vars(duration-200) vars(ease-out);
|
|
17
|
+
// ─────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
@use "sass:meta";
|
|
20
|
+
@use "sass:string";
|
|
21
|
+
@use "../variables/global" as g;
|
|
22
|
+
|
|
23
|
+
// Internal: the custom-property namespace prefix.
|
|
24
|
+
// Mirrors the --mastors- prefix used by the token emitter.
|
|
25
|
+
// Kept as a private variable so it only needs to change here.
|
|
26
|
+
$-namespace: "mastors" !default;
|
|
27
|
+
|
|
28
|
+
/// Return a CSS var() expression for a design token by name.
|
|
29
|
+
///
|
|
30
|
+
/// @param {String} $token - token name, without the --mastors- prefix
|
|
31
|
+
/// @param {*} $fallback - optional CSS fallback value (default: null)
|
|
32
|
+
/// @return {String} var(--mastors-{$token}) or var(--mastors-{$token}, {$fallback})
|
|
33
|
+
///
|
|
34
|
+
/// @example scss
|
|
35
|
+
/// .btn { color: vars(accent); }
|
|
36
|
+
/// // → .btn { color: var(--mastors-accent); }
|
|
37
|
+
///
|
|
38
|
+
/// @example scss
|
|
39
|
+
/// .card { box-shadow: vars(shadow-md, 0 2px 8px rgb(0 0 0 / .1)); }
|
|
40
|
+
/// // → .card { box-shadow: var(--mastors-shadow-md, 0 2px 8px rgb(0 0 0 / .1)); }
|
|
41
|
+
@function vars($token, $fallback: null) {
|
|
42
|
+
$prop: "--#{$-namespace}-#{$token}";
|
|
43
|
+
|
|
44
|
+
@if not $fallback {
|
|
45
|
+
@return var(#{$prop});
|
|
46
|
+
} @else {
|
|
47
|
+
@return var(#{$prop}, #{$fallback});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// generators/_class-generator.scss
|
|
2
|
+
// Core mixin engine for generating utility class output.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:map";
|
|
6
|
+
@use "sass:meta";
|
|
7
|
+
@use "sass:string";
|
|
8
|
+
@use "../config/settings" as cfg;
|
|
9
|
+
@use "../config/flags";
|
|
10
|
+
@use "../variables/breakpoints" as bpvars;
|
|
11
|
+
|
|
12
|
+
/// Core utility class generator engine.
|
|
13
|
+
@mixin generate-utilities($utilities) {
|
|
14
|
+
$cls-prefix: cfg.config("prefix");
|
|
15
|
+
$use-important: cfg.config("important");
|
|
16
|
+
|
|
17
|
+
// ── Pass 1: base (unprefixed) classes ──────────────────────
|
|
18
|
+
@each $name, $config in $utilities {
|
|
19
|
+
$prop: map.get($config, property);
|
|
20
|
+
$values: map.get($config, values);
|
|
21
|
+
$prefix: map.get($config, prefix);
|
|
22
|
+
|
|
23
|
+
@each $suffix, $value in $values {
|
|
24
|
+
$class-name: "#{$cls-prefix}#{$suffix}";
|
|
25
|
+
@if $prefix {
|
|
26
|
+
$class-name: "#{$cls-prefix}#{$prefix}-#{$suffix}";
|
|
27
|
+
}
|
|
28
|
+
.#{$class-name} {
|
|
29
|
+
@if $use-important {
|
|
30
|
+
#{$prop}: $value !important;
|
|
31
|
+
} @else {
|
|
32
|
+
#{$prop}: $value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ── Pass 2: responsive variants (.sm\:, .md\:, …) ─────────
|
|
39
|
+
@if flags.$enable-responsive {
|
|
40
|
+
@each $bp-key, $bp-value in bpvars.$breakpoints {
|
|
41
|
+
@if $bp-value != 0 {
|
|
42
|
+
@media (min-width: #{$bp-value}) {
|
|
43
|
+
@each $name, $config in $utilities {
|
|
44
|
+
@if map.get($config, responsive) == true {
|
|
45
|
+
$prop: map.get($config, property);
|
|
46
|
+
$values: map.get($config, values);
|
|
47
|
+
$prefix: map.get($config, prefix);
|
|
48
|
+
|
|
49
|
+
@each $suffix, $value in $values {
|
|
50
|
+
$class: null;
|
|
51
|
+
@if $prefix {
|
|
52
|
+
$class: "#{$cls-prefix}#{$prefix}-#{$suffix}";
|
|
53
|
+
} @else {
|
|
54
|
+
$class: "#{$cls-prefix}#{$suffix}";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Escape numeric-leading breakpoint keys (e.g. "2xl" → "\32 xl")
|
|
58
|
+
$first: string.slice("#{$bp-key}", 1, 1);
|
|
59
|
+
$rest: string.slice("#{$bp-key}", 2);
|
|
60
|
+
$safe-bp: null;
|
|
61
|
+
@if $first == "0" or $first == "1" or $first == "2" or $first == "3" or
|
|
62
|
+
$first == "4" or $first == "5" or $first == "6" or $first == "7" or
|
|
63
|
+
$first == "8" or $first == "9" {
|
|
64
|
+
$safe-bp: "\\3#{$first} #{$rest}";
|
|
65
|
+
} @else {
|
|
66
|
+
$safe-bp: "#{$bp-key}";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@at-root .#{$safe-bp}\:#{$class} {
|
|
70
|
+
@if $use-important {
|
|
71
|
+
#{$prop}: $value !important;
|
|
72
|
+
} @else {
|
|
73
|
+
#{$prop}: $value;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// generators/_custom-property-generator.scss
|
|
2
|
+
// Emits CSS custom properties from SCSS token maps.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:map";
|
|
6
|
+
@use "sass:meta";
|
|
7
|
+
@use "sass:string";
|
|
8
|
+
|
|
9
|
+
/// Emit CSS custom properties from a token map onto a selector
|
|
10
|
+
/// @param {Map} $map - token map (key → value)
|
|
11
|
+
/// @param {String} $prefix - custom property prefix (e.g. "mastors-color-primary")
|
|
12
|
+
@mixin emit-custom-properties($map, $prefix) {
|
|
13
|
+
@each $key, $value in $map {
|
|
14
|
+
--#{$prefix}-#{$key}: #{$value};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// Recursively emit nested token maps (e.g. color palette with scales)
|
|
19
|
+
/// @param {Map} $map - nested map
|
|
20
|
+
/// @param {String} $prefix - base prefix (e.g. "mastors-color")
|
|
21
|
+
@mixin emit-nested-custom-properties($map, $prefix) {
|
|
22
|
+
@each $key, $value in $map {
|
|
23
|
+
@if meta.type-of($value) == map {
|
|
24
|
+
@include emit-nested-custom-properties($value, "#{$prefix}-#{$key}");
|
|
25
|
+
} @else {
|
|
26
|
+
--#{$prefix}-#{$key}: #{$value};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// generators/_responsive-generator.scss
|
|
2
|
+
// Responsive variant delegation — forwards to the canonical engine.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
// NOTE: Responsive class generation is now handled directly inside
|
|
6
|
+
// generate-utilities() in _class-generator.scss (Pass 2).
|
|
7
|
+
// This file previously contained a generate-responsive() mixin that
|
|
8
|
+
// accepted @content blocks but never emitted any CSS itself, making it
|
|
9
|
+
// a silent no-op. That stub has been removed to prevent confusion.
|
|
10
|
+
// — If you need to run the responsive engine standalone (e.g. from a
|
|
11
|
+
// sub-package that builds its own $utilities map independently of
|
|
12
|
+
// generate-utilities), use the engine mixin directly:
|
|
13
|
+
// @use "@mastors/core/scss/responsive/engine" as engine;
|
|
14
|
+
// @include engine.run($my-utilities);
|
|
15
|
+
// — For the standard case, simply pass your $utilities map to
|
|
16
|
+
// generate-utilities() and set responsive: true on any entry that
|
|
17
|
+
// needs breakpoint variants — the responsive pass runs automatically.
|
|
18
|
+
|
|
19
|
+
@use "../responsive/engine" as engine;
|
|
20
|
+
@use "sass:map";
|
|
21
|
+
|
|
22
|
+
/// Thin wrapper that delegates to engine.run().
|
|
23
|
+
/// Prefer calling engine.run() directly for clarity.
|
|
24
|
+
/// Kept here only for backward compatibility with sub-packages that
|
|
25
|
+
/// previously @use'd this file.
|
|
26
|
+
@mixin generate-responsive($utilities) {
|
|
27
|
+
@include engine.run($utilities);
|
|
28
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// helpers/_ratio.scss
|
|
2
|
+
// Aspect ratio helpers.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:math";
|
|
6
|
+
|
|
7
|
+
// Aspect ratio helpers using the native aspect-ratio property
|
|
8
|
+
|
|
9
|
+
$-ratios: (
|
|
10
|
+
"auto": auto,
|
|
11
|
+
"square": math.div(1, 1),
|
|
12
|
+
"video": math.div(16, 9),
|
|
13
|
+
"portrait": math.div(3, 4),
|
|
14
|
+
"wide": math.div(21, 9),
|
|
15
|
+
"golden": math.div(1.618, 1),
|
|
16
|
+
) !default;
|
|
17
|
+
|
|
18
|
+
@each $name, $ratio in $-ratios {
|
|
19
|
+
.ratio-#{$name} {
|
|
20
|
+
aspect-ratio: $ratio;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// helpers/_truncate.scss
|
|
2
|
+
// Text truncation and overflow helpers.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
// Single-line truncation
|
|
6
|
+
.truncate {
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
text-overflow: ellipsis;
|
|
9
|
+
white-space: nowrap;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Multi-line clamp helpers (.line-clamp-{n})
|
|
13
|
+
@each $n in 1, 2, 3, 4, 5, 6 {
|
|
14
|
+
.line-clamp-#{$n} {
|
|
15
|
+
display: -webkit-box;
|
|
16
|
+
-webkit-line-clamp: $n;
|
|
17
|
+
-webkit-box-orient: vertical;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Break long words
|
|
23
|
+
.break-words { overflow-wrap: break-word; word-break: break-word; }
|
|
24
|
+
.break-all { word-break: break-all; }
|
|
25
|
+
.break-keep { word-break: keep-all; }
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// helpers/_visually-hidden.scss
|
|
2
|
+
// Visually hides content while keeping it accessible to screen readers.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
// The canonical implementation lives in accessibility/_screen-reader.scss
|
|
5
|
+
// (.sr-only / .not-sr-only — the modern standard class names).
|
|
6
|
+
// This file provides the legacy aliases (.visually-hidden, .vh,
|
|
7
|
+
// .visually-hidden-focusable) that map onto the same rules, so existing
|
|
8
|
+
// codebases using either naming convention continue to work without
|
|
9
|
+
// duplicating any declarations.
|
|
10
|
+
|
|
11
|
+
@use "../accessibility/screen-reader" as *;
|
|
12
|
+
|
|
13
|
+
// Legacy aliases — extend the canonical sr-only rules
|
|
14
|
+
// so no extra CSS is emitted; both class names share one rule block.
|
|
15
|
+
.visually-hidden,
|
|
16
|
+
.vh {
|
|
17
|
+
position: absolute;
|
|
18
|
+
width: 1px;
|
|
19
|
+
height: 1px;
|
|
20
|
+
padding: 0;
|
|
21
|
+
margin: -1px;
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
clip: rect(0, 0, 0, 0);
|
|
24
|
+
white-space: nowrap;
|
|
25
|
+
border-width: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Undo visually-hidden when focused (e.g. skip links)
|
|
29
|
+
.visually-hidden-focusable:not(:focus):not(:focus-within) {
|
|
30
|
+
position: absolute;
|
|
31
|
+
width: 1px;
|
|
32
|
+
height: 1px;
|
|
33
|
+
padding: 0;
|
|
34
|
+
margin: -1px;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
clip: rect(0, 0, 0, 0);
|
|
37
|
+
white-space: nowrap;
|
|
38
|
+
border-width: 0;
|
|
39
|
+
}
|
package/scss/index.scss
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @mastors/core — scss/index.scss
|
|
2
|
+
// ─────────────────────────────────────────────────────────────
|
|
3
|
+
// Main entry point for @mastors/core.
|
|
4
|
+
// Import order is intentional — do not reorder without reason.
|
|
5
|
+
// ─────────────────────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
// 1. Config & Settings (no output)
|
|
8
|
+
@use "config/settings" as *;
|
|
9
|
+
@use "config/flags" as *;
|
|
10
|
+
|
|
11
|
+
// 2. Abstracts (no output)
|
|
12
|
+
@use "abstracts/index" as *;
|
|
13
|
+
|
|
14
|
+
// 3. Variables & Tokens (no output)
|
|
15
|
+
@use "variables/index" as *;
|
|
16
|
+
@use "tokens/index" as *;
|
|
17
|
+
|
|
18
|
+
// 4. Functions (no output)
|
|
19
|
+
@use "functions/index" as *;
|
|
20
|
+
|
|
21
|
+
// 5. Mixins (no output)
|
|
22
|
+
@use "mixins/index" as *;
|
|
23
|
+
|
|
24
|
+
// 6. Base & Reset (outputs CSS)
|
|
25
|
+
@use "base/index" as base;
|
|
26
|
+
|
|
27
|
+
// 7. Themes (outputs CSS custom properties)
|
|
28
|
+
@use "themes/index" as themes;
|
|
29
|
+
|
|
30
|
+
// 8. Semantic layer (outputs CSS)
|
|
31
|
+
@use "semantic/index" as semantic;
|
|
32
|
+
|
|
33
|
+
// 9. Responsive engine (outputs CSS)
|
|
34
|
+
@use "responsive/index" as responsive;
|
|
35
|
+
|
|
36
|
+
// 10. Helpers & Utilities
|
|
37
|
+
@use "helpers/index" as helpers;
|
|
38
|
+
@use "utilities/index" as utilities;
|
|
39
|
+
|
|
40
|
+
// 11. Accessibility
|
|
41
|
+
@use "accessibility/index" as accessibility;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// mixins/_breakpoint.scss
|
|
2
|
+
// Responsive breakpoint mixin and variant helpers.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:map";
|
|
6
|
+
@use "../variables/breakpoints" as bpvars;
|
|
7
|
+
|
|
8
|
+
/// Emit styles at and above a named breakpoint (mobile-first)
|
|
9
|
+
/// @param {String} $bp - breakpoint key (sm, md, lg, xl, 2xl)
|
|
10
|
+
@mixin bp($bp) {
|
|
11
|
+
$value: map.get(bpvars.$breakpoints, $bp);
|
|
12
|
+
@if not $value {
|
|
13
|
+
@error "bp(): unknown breakpoint '#{$bp}'. Available: #{map.keys(bpvars.$breakpoints)}";
|
|
14
|
+
}
|
|
15
|
+
@if $value == 0 {
|
|
16
|
+
@content;
|
|
17
|
+
} @else {
|
|
18
|
+
@media (min-width: #{$value}) { @content; }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Alias
|
|
23
|
+
@mixin respond-to($bp) { @include bp($bp) { @content; } }
|
|
24
|
+
@mixin breakpoint-up($bp) { @include bp($bp) { @content; } }
|
|
25
|
+
|
|
26
|
+
/// Emit styles below a named breakpoint
|
|
27
|
+
@mixin breakpoint-down($bp) {
|
|
28
|
+
$value: map.get(bpvars.$breakpoints, $bp);
|
|
29
|
+
@if not $value {
|
|
30
|
+
@error "breakpoint-down(): unknown breakpoint '#{$bp}'";
|
|
31
|
+
}
|
|
32
|
+
@media (max-width: #{$value - 0.02px}) { @content; }
|
|
33
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// mixins/_container.scss
|
|
2
|
+
// Responsive container width / max-width / padding mixin.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:map";
|
|
6
|
+
@use "../variables/container" as cvars;
|
|
7
|
+
@use "./breakpoint" as bp;
|
|
8
|
+
|
|
9
|
+
/// Responsive container with max-width and horizontal padding
|
|
10
|
+
@mixin container {
|
|
11
|
+
width: 100%;
|
|
12
|
+
margin-inline: auto;
|
|
13
|
+
padding-inline: cvars.$container-padding-x;
|
|
14
|
+
|
|
15
|
+
@each $bp-key, $max-w in cvars.$container-max-widths {
|
|
16
|
+
@include bp.bp($bp-key) {
|
|
17
|
+
max-width: $max-w;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// mixins/_elevation.scss
|
|
2
|
+
// Box shadow / elevation scale mixin.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:map";
|
|
6
|
+
@use "../tokens/shadows" as sh;
|
|
7
|
+
|
|
8
|
+
/// Apply a shadow elevation level
|
|
9
|
+
/// @param {String} $level - shadow key (xs, sm, md, lg, xl, 2xl, inner, none)
|
|
10
|
+
@mixin elevation($level: "md") {
|
|
11
|
+
box-shadow: sh.shadow($level);
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// mixins/_pseudo.scss
|
|
2
|
+
// ::before / ::after pseudo-element helper mixins.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/// Generate a pseudo-element (::before / ::after)
|
|
6
|
+
/// @param {String} $display - display value (default: block)
|
|
7
|
+
/// @param {String} $pos - position value (default: absolute)
|
|
8
|
+
/// @param {String} $content - content value (default: "")
|
|
9
|
+
@mixin pseudo($display: block, $pos: absolute, $content: "") {
|
|
10
|
+
content: $content;
|
|
11
|
+
display: $display;
|
|
12
|
+
position: $pos;
|
|
13
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// mixins/_theme.scss
|
|
2
|
+
// Theme-switching mixins (light/dark/custom).
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "../config/settings" as cfg;
|
|
6
|
+
|
|
7
|
+
/// Apply styles inside the dark-mode context (class or media strategy)
|
|
8
|
+
@mixin dark-mode {
|
|
9
|
+
@if cfg.config("dark-mode") == "class" {
|
|
10
|
+
.dark & { @content; }
|
|
11
|
+
[data-theme="dark"] & { @content; }
|
|
12
|
+
} @else {
|
|
13
|
+
@media (prefers-color-scheme: dark) { @content; }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// Apply styles inside the light-mode context
|
|
18
|
+
@mixin light-mode {
|
|
19
|
+
@if cfg.config("dark-mode") == "class" {
|
|
20
|
+
.light & { @content; }
|
|
21
|
+
[data-theme="light"] & { @content; }
|
|
22
|
+
} @else {
|
|
23
|
+
@media (prefers-color-scheme: light) { @content; }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// Apply styles under a named theme class on :root/html
|
|
28
|
+
/// Usage: @include theme("ocean") { color: ...; }
|
|
29
|
+
@mixin theme($name) {
|
|
30
|
+
[data-theme="#{$name}"] & { @content; }
|
|
31
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// mixins/_transition.scss
|
|
2
|
+
// Transition helpers using token-driven durations and easings.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:list";
|
|
6
|
+
@use "../tokens/transitions" as tr;
|
|
7
|
+
|
|
8
|
+
/// Emit a transition using named token durations and easings
|
|
9
|
+
/// @param {List} $properties - CSS properties to transition (default: all)
|
|
10
|
+
/// @param {String} $duration - duration token key (default: "200")
|
|
11
|
+
/// @param {String} $easing - easing token key (default: "in-out")
|
|
12
|
+
@mixin transition($properties: (all), $duration: "200", $easing: "in-out") {
|
|
13
|
+
$dur: tr.duration($duration);
|
|
14
|
+
$ease: tr.easing($easing);
|
|
15
|
+
$transitions: ();
|
|
16
|
+
@each $prop in $properties {
|
|
17
|
+
$transitions: list.append($transitions, #{$prop} #{$dur} #{$ease}, comma);
|
|
18
|
+
}
|
|
19
|
+
transition: $transitions;
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// responsive/_container-queries.scss
|
|
2
|
+
// CSS container query helpers (@container).
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
// Container query helpers
|
|
6
|
+
// Requires elements to have a containment context set:
|
|
7
|
+
// .cq-inline { container-type: inline-size; }
|
|
8
|
+
// .cq-size { container-type: size; }
|
|
9
|
+
// .cq-normal { container-type: normal; }
|
|
10
|
+
|
|
11
|
+
.cq-inline { container-type: inline-size; }
|
|
12
|
+
.cq-size { container-type: size; }
|
|
13
|
+
.cq-normal { container-type: normal; }
|
|
14
|
+
|
|
15
|
+
// Named container helper
|
|
16
|
+
// Usage: <div class="cq-inline" style="container-name: card">...
|
|
17
|
+
// or use data attribute: [data-container] { container-type: inline-size; }
|
|
18
|
+
[data-container] {
|
|
19
|
+
container-type: inline-size;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Mixin for inline container queries in component SCSS
|
|
23
|
+
// @use "@mastors/core/api" as m;
|
|
24
|
+
// @include m.cq(40rem) { ... }
|
|
25
|
+
@mixin cq($min-width, $name: null) {
|
|
26
|
+
@if $name {
|
|
27
|
+
@container #{$name} (min-width: #{$min-width}) { @content; }
|
|
28
|
+
} @else {
|
|
29
|
+
@container (min-width: #{$min-width}) { @content; }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// responsive/_engine.scss
|
|
2
|
+
// Core responsive variant generation engine.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:map";
|
|
6
|
+
@use "../variables/breakpoints" as bpvars;
|
|
7
|
+
@use "../config/flags";
|
|
8
|
+
|
|
9
|
+
// Responsive engine — generates breakpoint-prefixed variants
|
|
10
|
+
// of any utility that declares responsive: true.
|
|
11
|
+
// Class pattern: .{bp}\:{utility}
|
|
12
|
+
// Example output: .sm\:hidden, .md\:flex, .lg\:gap-8
|
|
13
|
+
// Sub-packages pass their $utilities map here via @include engine.run()
|
|
14
|
+
// so the engine iterates breakpoints and re-emits the classes.
|
|
15
|
+
|
|
16
|
+
@use "sass:string";
|
|
17
|
+
|
|
18
|
+
@mixin run($utilities) {
|
|
19
|
+
@if flags.$enable-responsive {
|
|
20
|
+
@each $bp-key, $bp-value in bpvars.$breakpoints {
|
|
21
|
+
// Skip xs — no prefix, already emitted as base classes
|
|
22
|
+
@if $bp-value != 0 {
|
|
23
|
+
@media (min-width: #{$bp-value}) {
|
|
24
|
+
@each $name, $config in $utilities {
|
|
25
|
+
@if map.get($config, responsive) == true {
|
|
26
|
+
$prop: map.get($config, property);
|
|
27
|
+
$values: map.get($config, values);
|
|
28
|
+
$prefix: map.get($config, prefix);
|
|
29
|
+
|
|
30
|
+
@each $suffix, $value in $values {
|
|
31
|
+
$class: null;
|
|
32
|
+
@if $prefix {
|
|
33
|
+
$class: "#{$prefix}-#{$suffix}";
|
|
34
|
+
} @else {
|
|
35
|
+
$class: "#{$suffix}";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// CSS class names cannot start with a digit.
|
|
39
|
+
// When the breakpoint key begins with a number (e.g. "2xl"),
|
|
40
|
+
// escape it using the CSS identifier-escape syntax: \3X (space after hex).
|
|
41
|
+
$first: string.slice("#{$bp-key}", 1, 1);
|
|
42
|
+
$rest: string.slice("#{$bp-key}", 2);
|
|
43
|
+
$safe-bp: null;
|
|
44
|
+
@if $first == "0" or $first == "1" or $first == "2" or $first == "3" or
|
|
45
|
+
$first == "4" or $first == "5" or $first == "6" or $first == "7" or
|
|
46
|
+
$first == "8" or $first == "9" {
|
|
47
|
+
// \3X is the CSS escape for the digit (space terminates the escape)
|
|
48
|
+
$safe-bp: "\\3#{$first} #{$rest}";
|
|
49
|
+
} @else {
|
|
50
|
+
$safe-bp: "#{$bp-key}";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Use #{} interpolation so Sass emits the selector verbatim
|
|
54
|
+
// without re-parsing the leading backslash as a Sass identifier.
|
|
55
|
+
@at-root .#{$safe-bp}\:#{$class} {
|
|
56
|
+
#{$prop}: $value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// responsive/_fluid-type.scss
|
|
2
|
+
// Fluid / clamp()-based responsive typography scale.
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
@use "sass:math";
|
|
6
|
+
@use "../functions/math" as mathfn;
|
|
7
|
+
|
|
8
|
+
// Fluid type scale — font sizes that scale smoothly between two viewport widths.
|
|
9
|
+
// Uses clamp() so no media queries are needed.
|
|
10
|
+
// Usage in component SCSS:
|
|
11
|
+
// @use "@mastors/core/api" as m;
|
|
12
|
+
// font-size: m.fluid-type(1rem, 1.5rem);
|
|
13
|
+
|
|
14
|
+
/// Fluid type mixin: applies a clamp()-based fluid font-size
|
|
15
|
+
/// @param {Number} $min-size - minimum font size (rem)
|
|
16
|
+
/// @param {Number} $max-size - maximum font size (rem)
|
|
17
|
+
/// @param {Number} $min-vw - viewport at which min applies (px, default 320px)
|
|
18
|
+
/// @param {Number} $max-vw - viewport at which max applies (px, default 1280px)
|
|
19
|
+
@mixin apply-fluid-type($min-size, $max-size, $min-vw: 320px, $max-vw: 1280px) {
|
|
20
|
+
font-size: mathfn.fluid($min-size, $max-size, $min-vw, $max-vw);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// Fluid type function — for direct use in property values
|
|
24
|
+
/// @return {String} clamp() expression
|
|
25
|
+
@function fluid-type($min-size, $max-size, $min-vw: 320px, $max-vw: 1280px) {
|
|
26
|
+
@return mathfn.fluid($min-size, $max-size, $min-vw, $max-vw);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Predefined fluid heading scale (opt-in)
|
|
30
|
+
// Include with: @use "@mastors/core/scss/responsive/fluid-type" as ft;
|
|
31
|
+
// @include ft.fluid-scale();
|
|
32
|
+
@mixin fluid-scale {
|
|
33
|
+
h1 { @include apply-fluid-type(2rem, 3.75rem); }
|
|
34
|
+
h2 { @include apply-fluid-type(1.5rem, 3rem); }
|
|
35
|
+
h3 { @include apply-fluid-type(1.25rem, 2.25rem); }
|
|
36
|
+
h4 { @include apply-fluid-type(1.125rem, 1.875rem); }
|
|
37
|
+
h5 { @include apply-fluid-type(1rem, 1.5rem); }
|
|
38
|
+
h6 { @include apply-fluid-type(0.875rem, 1.25rem); }
|
|
39
|
+
p { @include apply-fluid-type(0.875rem, 1.125rem); }
|
|
40
|
+
}
|