sass-references/angular-material/material/core/theming/_m2-inspection.scss

271 lines
10 KiB
SCSS
Raw Normal View History

2024-12-06 10:42:08 +08:00
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use './theming';
@use '../m2/theming' as m2-theming;
@use '../m2/typography-utils' as m2-typography-utils;
@use '../typography/versioning' as typography-versioning;
/// Key used to access the Angular Material theme internals.
$_internals: _mat-theming-internals-do-not-access;
/// Keys that indicate a config object is a color config.
$_color-keys: (
primary,
accent,
warn,
foreground,
background,
is-dark,
color, /* included for themes that incorrectly nest the color config: (color: (color: (....))) */
);
/// Keys that indicate a config object is a typography config.
$_typography-keys: (
headline-1,
headline-2,
headline-3,
headline-4,
headline-5,
headline-6,
subtitle-1,
font-family,
subtitle-2,
body-1,
body-2,
button,
caption,
overline,
);
/// The CSS typography properties supported by the inspection API.
$_typography-properties: (font, font-family, line-height, font-size, letter-spacing, font-weight);
/// Gets the m2-config from the theme.
@function _get-m2-config($theme) {
// It is possible for a user to pass a "density theme" that is just a number.
@if meta.type-of($theme) != 'map' {
@return $theme;
}
$internal: map.get($theme, $_internals, m2-config);
$theme: map.remove($theme, $_internals);
@return if(_is-error-theme($theme), $internal, $theme);
}
/// Checks whether the given theme contains error values.
/// @param {*} $theme The theme to check.
/// @return {Boolean} true if the theme contains error values, else false.
@function _is-error-theme($theme) {
@if meta.type-of($theme) != 'map' {
@return false;
}
@if map.get($theme, ERROR) {
@return true;
}
@return _is-error-theme(list.nth(map.values($theme), 1));
}
/// Checks whether the given theme object has any of the given keys.
/// @param {Map} $theme The theme to check
/// @param {List} $keys The keys to check for
/// @return {Boolean} Whether the theme has any of the given keys.
@function _has-any-key($theme, $keys) {
@each $key in $keys {
@if map.has-key($theme, $key) {
@return true;
}
}
@return false;
}
/// Checks whether the given theme is a density scale value.
/// @param {*} $theme The theme to check.
/// @return {Boolean} true if the theme is a density scale value, else false.
@function _is-density-value($theme) {
@return $theme == minimum or $theme == maximum or meta.type-of($theme) == 'number';
}
/// 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) {
$theme: _get-m2-config($theme);
@if not theme-has($theme, color) {
@error 'Color information is not available on this theme.';
}
$colors: m2-theming.get-color-config($theme);
// Some apps seem to have mistakenly created nested color themes that somehow work with our old
// theme normalization logic. This check allows those apps to keep working.
@if theme-has($colors, color) {
$colors: m2-theming.get-color-config($colors);
}
@return if(map.get($colors, is-dark), dark, light);
}
/// Gets a color from a theme object. This function can take between 2 and 4 arguments. 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.
/// @param {Map} $theme The theme
/// @param {String} $palette-name 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).
/// @param {Number} $opacity The alpha channel value for the color.
/// @return {Color} The requested theme color.
@function get-theme-color($theme, $palette-name, $args...) {
$theme: _get-m2-config($theme);
@if not theme-has($theme, color) {
@error 'Color information is not available on this theme.';
}
$colors: m2-theming.get-color-config($theme);
// Some apps seem to have mistakenly created nested color themes that somehow work with our old
// theme normalization logic. This check allows those apps to keep working.
@if theme-has($colors, color) {
$colors: m2-theming.get-color-config($colors);
}
$palette: map.get($colors, $palette-name);
@if not $palette {
@error $palette-name $args $theme;
@error #{'Unrecognized palette name:'} $palette-name;
}
@return m2-theming.get-color-from-palette($palette, $args...);
}
/// 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) {
$theme: _get-m2-config($theme);
@if not theme-has($theme, typography) {
@error 'Typography information is not available on this theme.';
}
$typography: typography-versioning.private-typography-to-2018-config(
m2-theming.get-typography-config($theme));
@if $property == font {
$font-weight: m2-typography-utils.font-weight($typography, $typescale);
$font-size: m2-typography-utils.font-size($typography, $typescale);
$line-height: m2-typography-utils.line-height($typography, $typescale);
$font-family: m2-typography-utils.font-family($typography, $typescale);
@return ($font-weight list.slash($font-size, $line-height) $font-family);
}
@else if $property == font-family {
$result: m2-typography-utils.font-family($typography, $typescale);
@return $result or m2-typography-utils.font-family($typography);
}
@else if $property == font-size {
@return m2-typography-utils.font-size($typography, $typescale);
}
@else if $property == font-weight {
@return m2-typography-utils.font-weight($typography, $typescale);
}
@else if $property == line-height {
@return m2-typography-utils.line-height($typography, $typescale);
}
@else if $property == letter-spacing {
@return m2-typography-utils.letter-spacing($typography, $typescale);
}
@else {
@error #{'Valid typography properties are: #{$_typography-properties}. Got:'} $property;
}
}
/// Gets the density scale from a theme object.
/// @param {Map} $theme The theme
/// @return {Number} The density scale.
@function get-theme-density($theme) {
$theme: _get-m2-config($theme);
@if not theme-has($theme, density) {
@error 'Density information is not available on this theme.';
}
$scale: m2-theming.get-density-config($theme);
@return theming.clamp-density($scale, -5);
}
/// 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) {
$theme: _get-m2-config($theme);
@if $system == base {
@return true;
}
@if $system == color {
$color: m2-theming.get-color-config($theme);
@return $color != null and _has-any-key($color, $_color-keys);
}
@if $system == typography {
$typography: m2-theming.get-typography-config($theme);
@return $typography != null and _has-any-key($typography, $_typography-keys);
}
@if $system == density {
// Backwards compatibility for the case where an explicit, but invalid density is given
// (this was previously treated as density 0).
@if meta.type-of($theme) == 'map' and map.get($theme, density) {
@return true;
}
$density: m2-theming.get-density-config($theme);
@return $density != null and _is-density-value($density);
}
@error 'Valid systems are: base, color, typography, density. Got:' $system;
}
/// 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...) {
$internal: map.get($theme, $_internals, m2-config);
@each $system in $systems {
@if $system == color {
$theme: map.set($theme, color, null);
}
@else if $system == typography {
$theme: map.set($theme, typography, null);
}
@else if $system == density {
$theme: map.set($theme, density, null);
}
}
@if $internal {
$internal: theme-remove($internal, $systems...);
$theme: map.set($theme, $_internals, m2-config, $internal);
}
@return $theme;
}
/// 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) {
// It is possible for a user to pass a "density theme" that is just a number.
@if meta.type-of($theme) != 'map' {
@return $theme;
}
$internal: map.get($theme, $_internals, m2-config);
$theme: map.remove($theme, $_internals);
@if theme-has($theme, typography) {
$typography-config: m2-theming.get-typography-config($theme);
// gmat configs have both 2018 and 2014 keys.
@if (not typography-versioning.private-typography-is-2014-config($typography-config)) or
(not typography-versioning.private-typography-is-2018-config($typography-config)) {
@return $theme;
}
$new-typography-config: typography-versioning.private-typography-to-2018-config(
$typography-config, true);
// subtitle-2 is mapped differently by `private-typography-to-2014-config`.
$new-typography-config: map.set(
$new-typography-config, subtitle-2, map.get($new-typography-config, body-1));
$theme: if($theme == $typography-config, $new-typography-config,
map.set($theme, typography, $new-typography-config));
}
@if $internal {
$internal: private-get-typography-back-compat-theme($internal);
$theme: map.set($theme, $_internals, m2-config, $internal);
}
@return $theme;
}