sass-references/angular-material/material/core/theming/_inspection.scss

316 lines
12 KiB
SCSS

@use 'sass:list';
@use 'sass:map';
@use '../style/validation';
@use './m2-inspection';
$_internals: _mat-theming-internals-do-not-access;
$_m3-typescales: (
display-large,
display-medium,
display-small,
headline-large,
headline-medium,
headline-small,
title-large,
title-medium,
title-small,
label-large,
label-medium,
label-small,
body-large,
body-medium,
body-small,
);
$_typography-properties: (font, font-family, line-height, font-size, letter-spacing, font-weight);
/// Validates that the given value is a versioned theme object.
/// @param {Any} $theme The theme object to validate.
/// @return {Boolean|Null} true if the theme has errors, else null.
@function _validate-theme-object($theme) {
$err: validation.validate-type($theme, 'map') or
map.get($theme, $_internals, theme-version) == null;
@return if($err, true, null);
}
/// Gets the version number of a theme object. A theme that is not a valid versioned theme object is
/// considered to be version 0.
/// @param {Map} $theme The theme to check the version of
/// @return {Number} The version number of the theme (0 if unknown).
@function get-theme-version($theme) {
$err: _validate-theme-object($theme);
@return if($err, 0, map.get($theme, $_internals, theme-version) or 0);
}
/// Gets the type of theme represented by a theme object (light or dark).
/// @param {Map} $theme The theme
/// @return {String} The type of theme (either `light` or `dark`).
@function get-theme-type($theme) {
$version: get-theme-version($theme);
@if $version == 0 {
@return m2-inspection.get-theme-type($theme);
}
@else if $version == 1 {
@if not theme-has($theme, color) {
@error 'Color information is not available on this theme.';
}
@return map.get($theme, $_internals, theme-type) or light;
}
@else {
@error #{'Unrecognized theme version:'} $version;
}
}
/// Gets a color from a theme object. This function take a different amount of arguments depending
/// on if it's working with an M2 or M3 theme:
/// - With an M3 theme it accepts either 2 or 3 arguments. If 2 arguments are passed, the second
/// argument is treated as the name of a color role. If 3 arguments are passed, the second argument
/// is treated as the name of a color palette (primary, secondary, etc.) and the third is treated
/// as the palette hue (10, 50, etc.).
/// - With an M2 theme theme it accepts between 2 and 4 arguments, or the equivalent of calling
/// the `m2-get-theme-color` function. The first argument is the theme, the second one is the
/// palette from which to extract the color, the third one is the hue within the palette and the
/// fourth is the opacity of the returned color.
/// the second one is the
/// @param {Map} $theme The theme
/// @param {String} $color-role-or-palette-name The name of the color role to get, or the name of a
/// color palette.
/// @param {Number} $hue The palette hue to get (passing this argument means the second argument is
/// interpreted as a palette name).
/// @return {Color} The requested theme color.
@function get-theme-color($theme, $args...) {
$version: get-theme-version($theme);
$args-count: list.length($args) + 1;
// M2 theme
@if $version == 0 {
@if $args-count < 2 or $args-count > 4 {
@error 'Expected between 2 and 4 arguments when working with an M2 theme. ' +
'Got: #{$args-count}';
}
@return m2-inspection.get-theme-color($theme, $args...);
}
// M3 theme
@if $version == 1 {
@if $args-count < 2 or $args-count > 3 {
@error 'Expected either 2 or 3 arguments when working with an M3 theme. Got: #{$args-count}';
}
@return if($args-count == 2,
_get-theme-role-color($theme, $args...),
_get-theme-palette-color($theme, $args...)
);
}
@error 'Unrecognized theme version: #{$version}';
}
/// Gets a role color from a theme object.
/// @param {Map} $theme The theme
/// @param {String} $color-role-name The name of the color role to get.
/// @return {Color} The requested role color.
@function _get-theme-role-color($theme, $color-role-name) {
$err: _validate-theme-object($theme);
@if $err {
// TODO(mmalerba): implement for old style theme objects.
@error #{'get-theme-color does not support legacy theme objects.'};
}
@if not theme-has($theme, color) {
@error 'Color information is not available on this theme.';
}
$color-roles: map.get($theme, $_internals, color-tokens, (mdc, theme));
$result: map.get($color-roles, $color-role-name);
@if not $result {
@error #{'Valid color roles are: #{map.keys($color-roles)}. Got:'} $color-role-name;
}
@return $result;
}
/// Gets a palette color from a theme object.
/// @param {Map} $theme The theme
/// @param {String} $palette-name The name of the palette to get the color from.
/// @param {Number} $hue The hue to read from the palette.
/// @return {Color} The requested palette color.
@function _get-theme-palette-color($theme, $palette-name, $hue) {
$err: _validate-theme-object($theme);
@if $err {
// TODO(mmalerba): implement for old style theme objects.
@error #{'get-theme-color does not support legacy theme objects.'};
}
@if not theme-has($theme, color) {
@error 'Color information is not available on this theme.';
}
$palettes: map.get($theme, $_internals, palettes);
$palette: map.get($palettes, $palette-name);
@if not $palette {
$supported-palettes: map.keys($palettes);
@error #{'Valid palettes are: #{$supported-palettes}. Got:'} $palette-name;
}
$result: map.get($palette, $hue);
@if not $result {
$supported-hues: map.keys($palette);
@error #{'Valid hues for'} $palette-name #{'are: #{$supported-hues}. Got:'} $hue;
}
@return $result;
}
/// Gets a typography value from a theme object.
/// @param {Map} $theme The theme
/// @param {String} $typescale The typescale name.
/// @param {String} $property The CSS font property to get
/// (font, font-family, font-size, font-weight, line-height, or letter-spacing).
/// @return {*} The value of the requested font property.
@function get-theme-typography($theme, $typescale, $property: font) {
$version: get-theme-version($theme);
@if $version == 0 {
@return m2-inspection.get-theme-typography($theme, $typescale, $property);
}
@else if $version == 1 {
@if not theme-has($theme, typography) {
@error 'Typography information is not available on this theme.';
}
@if not list.index($_m3-typescales, $typescale) {
@error #{'Valid typescales are: #{$_m3-typescales}. Got:'} $typescale;
}
@if not list.index($_typography-properties, $property) {
@error #{'Valid typography properties are: #{$_typography-properties}. Got:'} $property;
}
$property-key: map.get((
font: '',
font-family: '-font',
line-height: '-line-height',
font-size: '-size',
letter-spacing: '-tracking',
font-weight: '-weight'
), $property);
$token-name: '#{$typescale}#{$property-key}';
@return map.get($theme, $_internals, typography-tokens, (mdc, typography), $token-name);
}
@else {
@error #{'Unrecognized theme version:'} $version;
}
}
/// Gets the density scale from a theme object.
/// @param {Map} $theme The theme
/// @return {Number} The density scale.
@function get-theme-density($theme) {
$version: get-theme-version($theme);
@if $version == 0 {
@return m2-inspection.get-theme-density($theme);
}
@else if $version == 1 {
@if not theme-has($theme, density) {
@error 'Density information is not available on this theme.';
}
@return map.get($theme, $_internals, density-scale);
}
@else {
@error #{'Unrecognized theme version:'} $version;
}
}
/// Checks whether the theme has information about given theming system.
/// @param {Map} $theme The theme
/// @param {String} $system The system to check
/// @param {Boolean} Whether the theme has information about the system.
@function theme-has($theme, $system) {
$version: get-theme-version($theme);
@if $version == 0 {
@return m2-inspection.theme-has($theme, $system);
}
@else if $version == 1 {
@if $system == base {
@return map.get($theme, $_internals, base-tokens) != null;
}
@if $system == color {
@return map.get($theme, $_internals, color-tokens) != null and
map.get($theme, $_internals, theme-type) != null and
map.get($theme, $_internals, palettes) != null;
}
@if $system == typography {
@return map.get($theme, $_internals, typography-tokens) != null;
}
@if $system == density {
@return map.get($theme, $_internals, density-scale) != null;
}
@error 'Valid systems are: base, color, typography, density. Got:' $system;
}
@else {
@error #{'Unrecognized theme version:'} $version;
}
}
/// Removes the information about the given theming system(s) from the given theme.
/// @param {Map} $theme The theme to remove information from
/// @param {String...} $systems The systems to remove
/// @return {Map} A version of the theme without the removed theming systems.
@function theme-remove($theme, $systems...) {
$err: validation.validate-allowed-values($systems, color, typography, density, base);
@if $err {
@error #{'Expected $systems to contain valid system names (color, typography, density, or'}
#{'base). Got invalid system names:'} $err;
}
$version: get-theme-version($theme);
@if $version == 0 {
@return m2-inspection.theme-remove($theme, $systems...);
}
@else if $version == 1 {
@each $system in $systems {
@if $system == base {
$theme: map.deep-remove($theme, $_internals, base-tokens);
}
@else if $system == color {
$theme: map.deep-remove($theme, $_internals, color-tokens);
$theme: map.deep-remove($theme, $_internals, theme-type);
$theme: map.deep-remove($theme, $_internals, palettes);
}
@else if $system == typography {
$theme: map.deep-remove($theme, $_internals, typography-tokens);
}
@else if $system == density {
$theme: map.deep-remove($theme, $_internals, density-scale);
$theme: map.deep-remove($theme, $_internals, density-tokens);
}
}
@return $theme;
}
}
/// Gets the set of tokens from the given theme, limited to those affected by the requested theming
/// systems.
/// @param {Map} $theme The theme to get tokens from.
/// @param {String...} $systems The theming systems to get tokens for. Valid values are: color,
/// typography, density, base. If no systems are passed, all tokens will be returned.
/// @return {Map} The requested tokens for the theme.
@function get-theme-tokens($theme, $systems...) {
$systems: if(list.length($systems) == 0, (color, typography, density, base), $systems);
$err: _validate-theme-object($theme);
@if $err {
@error #{'Expected $theme to be an Angular Material theme object. Got:'} $theme;
}
$err: validation.validate-allowed-values($systems, color, typography, density, base);
@if $err {
@error #{'Expected $systems to contain valid system names (color, typography, density, or'}
#{'base). Got invalid system names:'} $err;
}
$result: ();
@each $system in $systems {
$result: map.deep-merge($result, map.get($theme, $_internals, '#{$system}-tokens') or ());
}
@return $result;
}
/// Gets a version of the theme with a modified typography config that preserves old behavior in
/// some components that previously used `private-typography-to-2014-config`.
/// Do not introduce new usages of this, it should be cleaned up and removed.
/// @deprecated
@function private-get-typography-back-compat-theme($theme) {
@return if(
get-theme-version($theme) == 0,
m2-inspection.private-get-typography-back-compat-theme($theme),
$theme
);
}