273 lines
10 KiB
SCSS
273 lines
10 KiB
SCSS
@use '../style/elevation';
|
|
@use '../style/sass-utils';
|
|
@use '../theming/config-validation';
|
|
@use '../theming/definition';
|
|
@use './m3/definitions';
|
|
@use 'sass:map';
|
|
@use 'sass:meta';
|
|
@use 'sass:list';
|
|
@use './m3-tokens';
|
|
|
|
/// Emits necessary CSS variables for Material's system level values for the values defined in the
|
|
/// config map. The config map can have values color, typography, and/or density.
|
|
///
|
|
/// If the config map's color value is an Angular Material color palette, it will be used as the
|
|
/// primary and tertiary colors with a `color-scheme` theme type. Otherwise if the color value is a
|
|
/// map, it must have a `primary` value containing an Angular Material color palette, and
|
|
/// optionally a different `tertiary` palette (defaults to primary palette) and `theme-type` that
|
|
/// is either `light`, `dark`, or 'color-scheme` (defaults to `color-scheme`). Color variable
|
|
/// definitions will not be emitted if there are no color values in the config.
|
|
///
|
|
/// If the config map's typography value is a font family string, it will be used as the
|
|
/// plain and brand font family with default bold, medium, and regular weights of 700, 500, and 400,
|
|
/// respectfully. Otherwise if the typography value is a map, it must have a `plain-family` font
|
|
/// family value, and optionally a different `brand-family` font family (defaults to the plain
|
|
/// value) and weights for `bold-weight` (default: 700), `bold-weight` (default: 500), and
|
|
/// `bold-weight` (default: 400). Typography variable definitions will not be emitted if there are
|
|
/// no typography values in the config.
|
|
///
|
|
/// If the config map's density value is a number, it will be used as the density scale. Otherwise
|
|
/// if the density value is a map, it must have a `scale` value. Density variable definitions will
|
|
/// not be emitted if there are no density values in the config.
|
|
///
|
|
/// The application variables emitted use the namespace prefix "--mat-sys".
|
|
/// e.g. --mat-sys-surface: #E5E5E5
|
|
///
|
|
/// @param {Map} $config The color configuration with optional keys color, typography, or density.
|
|
@mixin theme($config, $overrides: ()) {
|
|
$color: map.get($config, color);
|
|
$color-config: null;
|
|
@if ($color) {
|
|
// validate-palette returns null if it is a valid M3 palette
|
|
$is-palette: config-validation.validate-palette($color) == null;
|
|
|
|
// Default to "color-scheme" theme type if the config's color does not provide one.
|
|
@if (not $is-palette and not map.has-key($color, theme-type)) {
|
|
$color: map.set($color, theme-type, color-scheme);
|
|
}
|
|
|
|
$color-config: if($is-palette,
|
|
definition.define-colors((primary: $color, theme-type: color-scheme)),
|
|
definition.define-colors($color));
|
|
@include system-level-colors($color-config, $overrides, definition.$system-fallback-prefix);
|
|
@include system-level-elevation($color-config, $overrides, definition.$system-fallback-prefix);
|
|
}
|
|
|
|
$typography: map.get($config, typography);
|
|
$typography-config: null;
|
|
@if ($typography) {
|
|
$typography-config: if(meta.type-of($typography) == 'map',
|
|
definition.define-typography($typography),
|
|
definition.define-typography((plain-family: $typography)));
|
|
@include system-level-typography(
|
|
$typography-config, $overrides, definition.$system-fallback-prefix);
|
|
}
|
|
|
|
$density: map.get($config, density);
|
|
$density-config: null;
|
|
@if ($density) {
|
|
$density-config: if(meta.type-of($density) == 'map',
|
|
definition.define-density($density),
|
|
definition.define-density((scale: $density)));
|
|
$scale: map.get($density-config, _mat-theming-internals-do-not-access, density-scale);
|
|
@if ($scale != 0) {
|
|
$all-tokens: m3-tokens.generate-density-tokens($scale);
|
|
@each $component-tokens in $all-tokens {
|
|
$namespace: list.nth($component-tokens, 1);
|
|
@each $tokens in list.nth($component-tokens, 2) {
|
|
--#{list.nth($namespace, 1)}-#{list.nth($namespace, 2)}-#{
|
|
list.nth($tokens, 1)}: #{list.nth($tokens, 2)};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@include system-level-shape($overrides: $overrides, $prefix: definition.$system-fallback-prefix);
|
|
@include system-level-state($overrides: $overrides, $prefix: definition.$system-fallback-prefix);
|
|
}
|
|
|
|
/// Emits the system-level CSS variables for each of the provided override values. E.g. to
|
|
/// change the primary color to red, use `mat.theme-overrides((primary: red));`
|
|
@mixin theme-overrides($overrides, $prefix: definition.$system-fallback-prefix) {
|
|
$sys-names: map-merge-all(
|
|
definitions.md-sys-color-values-light(),
|
|
definitions.md-sys-typescale-values(),
|
|
definitions.md-sys-elevation-values(),
|
|
definitions.md-sys-shape-values(),
|
|
definitions.md-sys-state-values());
|
|
|
|
& {
|
|
@each $name, $value in $overrides {
|
|
@if (map.has-key($sys-names, $name)) {
|
|
--#{$prefix}-#{$name}: #{map.get($overrides, $name)};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin system-level-colors($theme, $overrides: (), $prefix: null) {
|
|
$palettes: map.get($theme, _mat-theming-internals-do-not-access, palettes);
|
|
$base-palettes: (
|
|
neutral: map.get($palettes, neutral),
|
|
neutral-variant: map.get($palettes, neutral-variant),
|
|
secondary: map.get($palettes, secondary),
|
|
error: map.get($palettes, error),
|
|
);
|
|
|
|
$type: map.get($theme, _mat-theming-internals-do-not-access, theme-type);
|
|
$primary: map.merge(map.get($palettes, primary), $base-palettes);
|
|
$tertiary: map.merge(map.get($palettes, tertiary), $base-palettes);
|
|
$error: map.get($palettes, error);
|
|
|
|
@if (not $prefix) {
|
|
$prefix: map.get($theme, _mat-theming-internals-do-not-access,
|
|
color-system-variables-prefix) or definition.$system-level-prefix;
|
|
}
|
|
|
|
$ref: (
|
|
md-ref-palette: m3-tokens.generate-ref-palette-tokens($primary, $tertiary, $error)
|
|
);
|
|
|
|
$sys-colors: _generate-sys-colors($ref, $type);
|
|
|
|
// Manually insert a subset of palette values that are used directly by components
|
|
// instead of system variables.
|
|
$sys-colors: map.set($sys-colors,
|
|
'neutral-variant20', map.get($ref, md-ref-palette, neutral-variant20));
|
|
$sys-colors: map.set($sys-colors,
|
|
'neutral10', map.get($ref, md-ref-palette, neutral10));
|
|
|
|
& {
|
|
@each $name, $value in $sys-colors {
|
|
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
|
|
}
|
|
}
|
|
}
|
|
|
|
@function _generate-sys-colors($ref, $type) {
|
|
$light-sys-colors: definitions.md-sys-color-values-light($ref);
|
|
@if ($type == light) {
|
|
@return $light-sys-colors;
|
|
}
|
|
|
|
$dark-sys-colors: definitions.md-sys-color-values-dark($ref);
|
|
@if ($type == dark) {
|
|
@return $dark-sys-colors;
|
|
}
|
|
|
|
@if ($type == color-scheme) {
|
|
$light-dark-sys-colors: ();
|
|
@each $name, $light-value in $light-sys-colors {
|
|
$dark-value: map.get($dark-sys-colors, $name);
|
|
$light-dark-sys-colors:
|
|
map.set($light-dark-sys-colors, $name, light-dark($light-value, $dark-value));
|
|
}
|
|
@return $light-dark-sys-colors;
|
|
}
|
|
|
|
@error 'Unknown theme-type provided: #{$type}';
|
|
}
|
|
|
|
@mixin system-level-typography($theme, $overrides: (), $prefix: null) {
|
|
$font-definition: map.get($theme, _mat-theming-internals-do-not-access, font-definition);
|
|
$brand: map.get($font-definition, brand);
|
|
$plain: map.get($font-definition, plain);
|
|
$bold: map.get($font-definition, bold);
|
|
$medium: map.get($font-definition, medium);
|
|
$regular: map.get($font-definition, regular);
|
|
$ref: (md-ref-typeface:
|
|
m3-tokens.generate-ref-typeface-tokens($brand, $plain, $bold, $medium, $regular)
|
|
);
|
|
|
|
@if (not $prefix) {
|
|
$prefix: map.get($theme, _mat-theming-internals-do-not-access,
|
|
typography-system-variables-prefix) or definition.$system-level-prefix;
|
|
}
|
|
|
|
& {
|
|
@each $name, $value in definitions.md-sys-typescale-values($ref) {
|
|
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin system-level-elevation($theme, $overrides: (), $prefix: definition.$system-level-prefix) {
|
|
$shadow-color: map.get(
|
|
$theme, _mat-theming-internals-do-not-access, color-tokens, (mdc, theme), shadow);
|
|
|
|
@each $name, $value in definitions.md-sys-elevation-values() {
|
|
$level: map.get($overrides, $name) or $value;
|
|
$value: elevation.get-box-shadow($level, $shadow-color);
|
|
& {
|
|
--#{$prefix}-#{$name}: #{$value};
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin system-level-shape($theme: (), $overrides: (), $prefix: definition.$system-level-prefix) {
|
|
& {
|
|
@each $name, $value in definitions.md-sys-shape-values() {
|
|
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
|
|
}
|
|
}
|
|
}
|
|
|
|
@mixin system-level-state($theme: (), $overrides: (), $prefix: definition.$system-level-prefix) {
|
|
& {
|
|
@each $name, $value in definitions.md-sys-state-values() {
|
|
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return a new map where the values are the same as the provided map's
|
|
// keys, prefixed with "--mat-sys-". For example:
|
|
// (key1: '', key2: '') --> (key1: --mat-sys-key1, key2: --mat-sys-key2)
|
|
@function _create-system-app-vars-map($map) {
|
|
$new-map: ();
|
|
@each $key, $value in $map {
|
|
$new-map: map.set($new-map, $key, --#{definition.$system-fallback-prefix}-#{$key});
|
|
}
|
|
@return $new-map;
|
|
}
|
|
|
|
// Create a components tokens map where values are based on
|
|
// system fallback variables referencing Material's system keys.
|
|
// Includes density token fallbacks where density is 0.
|
|
@function create-system-fallbacks() {
|
|
$app-vars: (
|
|
'md-sys-color':
|
|
_create-system-app-vars-map(definitions.md-sys-color-values-light()),
|
|
'md-sys-typescale':
|
|
_create-system-app-vars-map(definitions.md-sys-typescale-values()),
|
|
'md-sys-elevation':
|
|
_create-system-app-vars-map(definitions.md-sys-elevation-values()),
|
|
'md-sys-state':
|
|
_create-system-app-vars-map(definitions.md-sys-state-values()),
|
|
'md-sys-shape':
|
|
_create-system-app-vars-map(definitions.md-sys-shape-values()),
|
|
// Add a subset of palette-specific colors used by components instead of system values
|
|
'md-ref-palette':
|
|
_create-system-app-vars-map(
|
|
(
|
|
neutral10: '', // Form field native select option text color
|
|
neutral-variant20: '', // Sidenav scrim (container background shadow when opened),
|
|
)
|
|
),
|
|
);
|
|
|
|
@return sass-utils.deep-merge-all(
|
|
m3-tokens.generate-tokens($app-vars, true, true),
|
|
m3-tokens.generate-density-tokens(0)
|
|
);
|
|
}
|
|
|
|
/// Creates a single merged map from the provided variable-length map arguments
|
|
@function map-merge-all($maps...) {
|
|
$result: ();
|
|
@each $map in $maps {
|
|
$result: map.merge($result, $map);
|
|
}
|
|
@return $result;
|
|
}
|