Skip to content

Commit

Permalink
main - d679024 feat(material/core): move Material 3 support into stab…
Browse files Browse the repository at this point in the history
…le (#28913)
  • Loading branch information
crisbeto committed Apr 19, 2024
1 parent 15b6317 commit c78cf6e
Show file tree
Hide file tree
Showing 14 changed files with 4,524 additions and 15 deletions.
7 changes: 7 additions & 0 deletions _index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
// New theming APIs
@forward './core/theming/inspection' show get-theme-version, get-theme-type, get-theme-color,
get-theme-typography, get-theme-density, theme-has, theme-remove;
@forward './core/theming/definition' show define-theme, define-colors, define-typography,
define-density;
@forward './core/theming/palettes' show $red-palette, $green-palette, $blue-palette,
$yellow-palette, $cyan-palette, $magenta-palette, $orange-palette,
$chartreuse-palette, $azure-palette, $violet-palette, $rose-palette;
@forward './core/theming/color-api-backwards-compatibility' show
color-variants-backwards-compatibility;

@forward './core/theming/theming' show $theme-ignore-duplication-warnings,
$theme-legacy-inspection-api-compatibility;
Expand Down
128 changes: 128 additions & 0 deletions core/theming/_color-api-backwards-compatibility.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
@use '../../badge/badge-theme';
@use '../../button/button-theme';
@use '../../button/fab-theme';
@use '../../checkbox/checkbox-theme';
@use '../../chips/chips-theme';
@use '../../datepicker/datepicker-theme';
@use '../../icon/icon-theme';
@use '../../progress-bar/progress-bar-theme';
@use '../../progress-spinner/progress-spinner-theme';
@use '../../radio/radio-theme';
@use '../../select/select-theme';
@use '../../slide-toggle/slide-toggle-theme';
@use '../../slider/slider-theme';
@use '../../stepper/stepper-theme';
@use '../../tabs/tabs-theme';
@use '../../form-field/form-field-theme';
@use '../option/option-theme';
@use '../selection/pseudo-checkbox/pseudo-checkbox-theme';

// We want to emit only the overrides, because the backwards compatibility styles are usually
// emitted after all the tokens have been included once already. This allows us to save ~50kb
// from the bundle.
$_overrides-only: true;

@mixin color-variant-styles($theme, $color-variant) {
$primary-options: (color-variant: $color-variant, emit-overrides-only: $_overrides-only);

// Some components use the secondary color rather than primary color for `.mat-primary`.
// Those components should use the $secondary-color-variant.
$secondary-options: (
color-variant: if($color-variant == primary, secondary, $color-variant),
emit-overrides-only: $_overrides-only
);

@include option-theme.color($theme, $secondary-options...);
@include progress-spinner-theme.color($theme, $primary-options...);
@include pseudo-checkbox-theme.color($theme, $primary-options...);
@include stepper-theme.color($theme, $primary-options...);

&.mat-icon {
@include icon-theme.color($theme, $primary-options...);
}

&.mat-mdc-checkbox {
@include checkbox-theme.color($theme, $primary-options...);
}

&.mat-mdc-slider {
@include slider-theme.color($theme, $primary-options...);
}

&.mat-mdc-tab-group,
&.mat-mdc-tab-nav-bar {
@include tabs-theme.color($theme, $primary-options...);
}

&.mat-mdc-slide-toggle {
@include slide-toggle-theme.color($theme, $primary-options...);
}

&.mat-mdc-form-field {
@include select-theme.color($theme, $primary-options...);
}

&.mat-mdc-radio-button {
@include radio-theme.color($theme, $primary-options...);
}

&.mat-mdc-progress-bar {
@include progress-bar-theme.color($theme, $primary-options...);
}

&.mat-mdc-form-field {
@include form-field-theme.color($theme, $primary-options...);
}

&.mat-datepicker-content {
@include datepicker-theme.color($theme, $primary-options...);
}

&.mat-mdc-button-base {
@include button-theme.color($theme, $primary-options...);
}

&.mat-mdc-standard-chip {
@include chips-theme.color($theme, $secondary-options...);
}

.mdc-list-item__start,
.mdc-list-item__end {
@include checkbox-theme.color($theme, $primary-options...);
@include radio-theme.color($theme, $primary-options...);
}

// M3 dropped support for warn/error color FABs.
@if $color-variant != error {
&.mat-mdc-fab,
&.mat-mdc-mini-fab {
@include fab-theme.color($theme, $primary-options...);
}
}
}

@mixin color-variants-backwards-compatibility($theme) {
.mat-primary {
@include color-variant-styles($theme, primary);
}
.mat-badge {
@include badge-theme.color($theme, $color-variant: primary,
$emit-overrides-only: $_overrides-only);
}

.mat-accent {
@include color-variant-styles($theme, tertiary);
}
.mat-badge-accent {
@include badge-theme.color($theme, $color-variant: tertiary,
$emit-overrides-only: $_overrides-only);
}

.mat-warn {
@include color-variant-styles($theme, error);
}
.mat-badge-warn {
@include badge-theme.color($theme, $color-variant: error,
$emit-overrides-only: $_overrides-only);
}
}
166 changes: 166 additions & 0 deletions core/theming/_config-validation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use 'sass:string';
@use '../style/validation';
@use './palettes';

/// Creates an error message by finding `$config` in the existing message and appending a suffix to
/// it.
/// @param {List|String} $err The error message.
/// @param {String} $suffix The suffix to add.
/// @return {List|String} The updated error message.
@function _create-dollar-config-error-message($err, $suffix) {
@if meta.type-of($err) == 'list' {
@for $i from 1 through list.length($err) {
$err: list.set-nth($err, $i,
_create-dollar-config-error-message(list.nth($err, $i), $suffix));
}
}
@else if meta.type-of($err) == 'string' {
$start: string.index($err, '$config');
@if $start {
$err: string.insert($err, $suffix, $start + 7);
}
}
@return $err;
}

/// Validates that the given object is an M3 palette.
/// @param {*} $palette The object to test
/// @return {Boolean|null} null if it is a valid M3 palette, else true.
@function _validate-palette($palette) {
@if not meta.type-of($palette) == 'map' {
@return true;
}
$keys: map.keys($palette);
$expected-keys: map.keys(palettes.$red-palette);
@if validation.validate-allowed-values($keys, $expected-keys...) or
validation.validate-required-values($keys, $expected-keys...) {
@return true;
}
$nv-keys: map.keys(map.get($palette, neutral-variant));
$expected-nv-keys: map.keys(map.get(palettes.$red-palette, neutral-variant));
@if validation.validate-allowed-values($nv-keys, $expected-nv-keys...) or
validation.validate-required-values($nv-keys, $expected-nv-keys...) {
@return true;
}
@return null;
}

/// Validates a theme config.
/// @param {Map} $config The config to test.
/// @return {List} null if no error, else the error message
@function validate-theme-config($config) {
$err: validation.validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config should be a configuration object. Got:'} $config);
}
$allowed: (color, typography, density);
$err: validation.validate-allowed-values(map.keys($config or ()), $allowed...);
@if $err {
@return (
#{'$config has unexpected properties. Valid properties are'}
#{'#{$allowed}.'}
#{'Found:'}
$err
);
}
$err: validate-color-config(map.get($config, color));
@if $err {
@return _create-dollar-config-error-message($err, '.color');
}
$err: validate-typography-config(map.get($config, typography));
@if $err {
@return _create-dollar-config-error-message($err, '.typography');
}
$err: validate-density-config(map.get($config, density));
@if $err {
@return _create-dollar-config-error-message($err, '.density');
}
@return null;
}

/// Validates a theme color config.
/// @param {Map} $config The config to test.
/// @return {List} null if no error, else the error message
@function validate-color-config($config) {
$err: validation.validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config should be a color configuration object. Got:'} $config);
}
$allowed: (theme-type, primary, tertiary);
$err: validation.validate-allowed-values(map.keys($config or ()), $allowed...);
@if $err {
@return (
#{'$config has unexpected properties. Valid properties are'}
#{'#{$allowed}.'}
#{'Found:'}
$err
);
}
@if $config and map.has-key($config, theme-type) and
not list.index((light, dark), map.get($config, theme-type)) {
@return (
#{'Expected $config.theme-type to be one of: light, dark. Got:'}
map.get($config, theme-type)
);
}
@each $palette in (primary, secondary, tertiary) {
@if $config and map.has-key($config, $palette) {
$err: _validate-palette(map.get($config, $palette));
@if $err {
@return (
#{'Expected $config.#{$palette} to be a valid M3 palette. Got:'}
map.get($config, $palette)
);
}
}
}
@return null;
}

/// Validates a theme typography config.
/// @param {Map} $config The config to test.
/// @return {List} null if no error, else the error message
@function validate-typography-config($config) {
$err: validation.validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config should be a typography configuration object. Got:'} $config);
}
$allowed: (brand-family, plain-family, bold-weight, medium-weight, regular-weight);
$err: validation.validate-allowed-values(map.keys($config or ()), $allowed...);
@if $err {
@return (
#{'$config has unexpected properties. Valid properties are'}
#{'#{$allowed}.'}
#{'Found:'}
$err
);
}
@return null;
}

/// Validates a theme density config.
/// @param {Map} $config The config to test.
/// @return {List} null if no error, else the error message
@function validate-density-config($config) {
$err: validation.validate-type($config, 'map', 'null');
@if $err {
@return (#{'$config should be a density configuration object. Got:'} $config);
}
$err: validation.validate-allowed-values(map.keys($config or ()), scale);
@if $err {
@return (#{'$config has unexpected properties. Valid properties are: scale. Found:'} $err);
}
@if $config and map.has-key($config, scale) {
$allowed-scales: (0, -1, -2, -3, -4, -5, minimum, maximum);
@if validation.validate-allowed-values(map.get($config, scale), $allowed-scales...) {
@return (
#{'Expected $config.scale to be one of: #{$allowed-scales}. Got:'}
map.get($config, scale)
);
}
}
@return null;
}

0 comments on commit c78cf6e

Please sign in to comment.