@use 'sass:map'; @use '../style/sass-utils'; @use '../m2' as m2-theming; @use './m3'; @use './m3/definitions' as m3-token-definitions; @use '../tokens/m2' as m2-tokens; @use './density'; @use './format-tokens'; /// Generates tokens for the given palette with the given prefix. /// @param {Map} $palette The palette to generate tokens for /// @param {String} $prefix The key prefix used to name the tokens /// @return {Map} A set of tokens for the given palette @function _generate-palette-tokens($palette, $prefix) { $palette: map.remove($palette, neutral, neutral-variant); $result: (); @each $hue, $value in $palette { $result: map.set($result, '#{$prefix}#{$hue}', $value); } @return $result; } /// Creates a set of `md-ref-palette` tokens from the given palettes. (See /// ./m3/definitions/_md-ref-palette.scss) /// @param {Map} $primary The primary palette /// @param {Map} $secondary The secondary palette /// @param {Map} $tertiary The tertiary palette /// @param {Map} $error The error palette /// @return {Map} A set of `md-ref-palette` tokens @function generate-ref-palette-tokens($primary, $tertiary, $error) { @return sass-utils.merge-all( (black: #000, white: #fff), _generate-palette-tokens($primary, primary), _generate-palette-tokens(map.get($primary, secondary), secondary), _generate-palette-tokens($tertiary, tertiary), _generate-palette-tokens(map.get($primary, neutral), neutral), _generate-palette-tokens(map.get($primary, neutral-variant), neutral-variant), _generate-palette-tokens($error, error), ); } /// Creates a set of `md-ref-typeface` tokens from the given palettes. (See /// ./m3/definitions/_md-ref-typeface.scss) /// @param {List|String} $brand The font-family to use for brand text /// @param {List|String} $plain The font-family to use for plain text /// @param {String} $bold The font-weight to use for bold text /// @param {String} $medium The font-weight to use for medium text /// @param {String} $regular The font-weight to use for regular text /// @return {Map} A set of `md-ref-typeface` tokens @function generate-ref-typeface-tokens($brand, $plain, $bold, $medium, $regular) { @return ( brand: $brand, plain: $plain, weight-bold: $bold, weight-medium: $medium, weight-regular: $regular, ); } $_cached-token-slots: null; /// Determines the token slots for all components. @function _get-token-slots() { // Cache the slots since they're constant and calculating // them appears to be expensive (see #29009). @if ($_cached-token-slots) { @return $_cached-token-slots; } // TODO(mmalerba): Refactor this to not depend on the legacy theme when moving out of // material-experimental. This is a hack for now because there is no good way to get the token // slots in material-experimental without exposing them all from material. $fake-theme: m2-theming.define-light-theme(( color: ( primary: m2-theming.define-palette(m2-theming.$red-palette), accent: m2-theming.define-palette(m2-theming.$red-palette), warn: m2-theming.define-palette(m2-theming.$red-palette), ), typography: m2-theming.define-typography-config(), density: 0 )); $_cached-token-slots: m2-tokens.m2-tokens-from-theme($fake-theme) !global; @return $_cached-token-slots; } /// Generates a set of namespaced tokens for all components. /// @param {Map} $systems The MDC system tokens /// @param {Boolean} $include-non-systemized Whether to include non-systemized tokens /// @param {Boolean} $include-density Whether to include density tokens /// @return {Map} A map of namespaced tokens @function generate-tokens($systems, $include-non-systemized: false, $include-density: false) { $systems: map.merge(( md-sys-color: (), md-sys-elevation: (), md-sys-motion: (), md-sys-shape: (), md-sys-state: (), md-sys-typescale: () ), $systems); $exclude-hardcoded: not $include-non-systemized; // DO NOT REMOVE // This function is used internally. $systems: format-tokens.private-format-tokens($systems); $token-slots: _get-token-slots(); // TODO(mmalerba): Fill in remaining tokens. $result: sass-utils.deep-merge-all( // Add the system color & typography tokens (so we can give users access via an API). ( (mdc, theme): map.get($systems, md-sys-color), (mdc, typography): map.get($systems, md-sys-typescale), ), m3.get-m3-tokens($systems, $exclude-hardcoded, $token-slots), ); // Strip out tokens that are systemized by our made up density system. @each $namespace, $tokens in $result { @each $token, $value in $tokens { @if density.is-systemized($namespace, $token) and not $include-density { $tokens: map.remove($tokens, $token); } } $result: map.set($result, $namespace, $tokens); } @return $result; } @function create-map($keys, $prefix) { $result: (); @each $key in $keys { $result: map.merge($result, ($key: var(--#{$prefix}-#{$key}))); } @return $result; } @function _get-sys-color($type, $ref, $prefix) { $mdc-sys-color: if($type == dark, m3-token-definitions.md-sys-color-values-dark($ref), m3-token-definitions.md-sys-color-values-light($ref)); @if (sass-utils.$use-system-color-variables) { $keys: ( 'background', 'error', 'error-container', 'inverse-on-surface', 'inverse-primary', 'inverse-surface', 'on-background', 'on-error', 'on-error-container', 'on-primary', 'on-primary-container', 'on-primary-fixed', 'on-primary-fixed-variant', 'on-secondary', 'on-secondary-container', 'on-secondary-fixed', 'on-secondary-fixed-variant', 'on-surface', 'on-surface-variant', 'on-tertiary', 'on-tertiary-container', 'on-tertiary-fixed', 'on-tertiary-fixed-variant', 'outline', 'outline-variant', 'primary', 'primary-container', 'primary-fixed', 'primary-fixed-dim', 'scrim', 'secondary', 'secondary-container', 'secondary-fixed', 'secondary-fixed-dim', 'surface', 'surface-bright', 'surface-container', 'surface-container-high', 'surface-container-highest', 'surface-container-low', 'surface-container-lowest', 'surface-dim', 'surface-tint', 'surface-variant', 'tertiary', 'tertiary-container', 'tertiary-fixed', 'tertiary-fixed-dim' ); @return map.merge(create-map($keys, $prefix), ( shadow: map.get($mdc-sys-color, shadow) )); } @return $mdc-sys-color; } @function _get-sys-typeface($ref, $prefix) { @if (sass-utils.$use-system-typography-variables) { $keys: ( 'body-large', 'body-large-font', 'body-large-line-height', 'body-large-size', 'body-large-tracking', 'body-large-weight', 'body-medium', 'body-medium-font', 'body-medium-line-height', 'body-medium-size', 'body-medium-tracking', 'body-medium-weight', 'body-small', 'body-small-font', 'body-small-line-height', 'body-small-size', 'body-small-tracking', 'body-small-weight', 'display-large', 'display-large-font', 'display-large-line-height', 'display-large-size', 'display-large-tracking', 'display-large-weight', 'display-medium', 'display-medium-font', 'display-medium-line-height', 'display-medium-size', 'display-medium-tracking', 'display-medium-weight', 'display-small', 'display-small-font', 'display-small-line-height', 'display-small-size', 'display-small-tracking', 'display-small-weight', 'headline-large', 'headline-large-font', 'headline-large-line-height', 'headline-large-size', 'headline-large-tracking', 'headline-large-weight', 'headline-medium', 'headline-medium-font', 'headline-medium-line-height', 'headline-medium-size', 'headline-medium-tracking', 'headline-medium-weight', 'headline-small', 'headline-small-font', 'headline-small-line-height', 'headline-small-size', 'headline-small-tracking', 'headline-small-weight', 'label-large', 'label-large-font', 'label-large-line-height', 'label-large-size', 'label-large-tracking', 'label-large-weight', 'label-large-weight-prominent', 'label-medium', 'label-medium-font', 'label-medium-line-height', 'label-medium-size', 'label-medium-tracking', 'label-medium-weight', 'label-medium-weight-prominent', 'label-small', 'label-small-font', 'label-small-line-height', 'label-small-size', 'label-small-tracking', 'label-small-weight', 'title-large', 'title-large-font', 'title-large-line-height', 'title-large-size', 'title-large-tracking', 'title-large-weight', 'title-medium', 'title-medium-font', 'title-medium-line-height', 'title-medium-size', 'title-medium-tracking', 'title-medium-weight', 'title-small', 'title-small-font', 'title-small-line-height', 'title-small-size', 'title-small-tracking', 'title-small-weight' ); @return create-map($keys, $prefix); } @return m3-token-definitions.md-sys-typescale-values($ref); } /// Generates a set of namespaced color tokens for all components. /// @param {String} $type The type of theme system (light or dark) /// @param {Map} $primary The primary palette /// @param {Map} $tertiary The tertiary palette /// @param {Map} $error The error palette /// @param {String} $system-variables-prefix The prefix of system tokens /// @return {Map} A map of namespaced color tokens @function generate-color-tokens($type, $primary, $tertiary, $error, $system-variables-prefix) { $ref: ( md-ref-palette: generate-ref-palette-tokens($primary, $tertiary, $error) ); $sys-color: _get-sys-color($type, $ref, $system-variables-prefix); @return generate-tokens(map.merge($ref, ( md-sys-color: $sys-color, // Because the elevation values are always combined with color values to create the box shadow, // elevation needs to be part of the color dimension. md-sys-elevation: m3-token-definitions.md-sys-elevation-values(), // Because the state values are sometimes combined with color values to create rgba colors, // state needs to be part of color dimension. // TODO(mmalerba): If at some point we remove the need for these combined values, we can move // state to the base dimension. md-sys-state: m3-token-definitions.md-sys-state-values(), ))); } /// Generates a set of namespaced color tokens for all components. /// @param {String|List} $brand The brand font-family /// @param {String|List} $plain The plain fort-family /// @param {String|Number} $bold The bold font-weight /// @param {String|Number} $medium The medium font-weight /// @param {String|Number} $regular The regular font-weight /// @param {String} $system-variables-prefix The prefix of system tokens /// @return {Map} A map of namespaced typography tokens @function generate-typography-tokens($brand, $plain, $bold, $medium, $regular, $system-variables-prefix) { $ref: ( md-ref-typeface: generate-ref-typeface-tokens($brand, $plain, $bold, $medium, $regular) ); $sys-typeface: _get-sys-typeface($ref, $system-variables-prefix); @return generate-tokens(( md-sys-typescale: $sys-typeface )); } /// Generates a set of namespaced density tokens for all components. /// @param {String|Number} $scale The regular font-weight /// @return {Map} A map of namespaced density tokens @function generate-density-tokens($scale) { @return density.get-tokens-for-scale($scale); } /// Generates a set of namespaced tokens not related to color, typography, or density for all /// components. /// @return {Map} A map of namespaced tokens not related to color, typography, or density @function generate-base-tokens() { // TODO(mmalerba): Exclude density tokens once implemented. @return generate-tokens(( md-sys-motion: m3-token-definitions.md-sys-motion-values(), md-sys-shape: m3-token-definitions.md-sys-shape-values(), ), $include-non-systemized: true); }