mirror of
https://github.com/material-components/material-web.git
synced 2024-09-21 02:27:12 +03:00
41d41cc278
PiperOrigin-RevId: 455635969
187 lines
5.8 KiB
SCSS
187 lines
5.8 KiB
SCSS
//
|
|
// Copyright 2022 Google LLC
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
@use 'sass:list';
|
|
@use 'sass:map';
|
|
@use 'sass:meta';
|
|
@use 'sass:string';
|
|
@use './assert';
|
|
@use './string-ext';
|
|
@use './var';
|
|
|
|
///
|
|
/// @example - scss
|
|
/// @debug color-var-hex-to-rgba(var(--foo-color-on-surface, #8ab4f8), 0.38);
|
|
/// // rgb(var(--foo-color-on-surface-rgb, 138, 180, 248), 0.38))
|
|
/// @param {String} $var - CSS custom property string in var(--foo, #hex) format.
|
|
/// @param {Number} $opacity - Opacity to mix with given color.
|
|
/// @return {String} Returns color string in rgb() format containing
|
|
/// CSS custom property for comma separated rgb color.
|
|
@function color-var-hex-to-rgba($var, $opacity) {
|
|
@if not var.is-var($var) {
|
|
@error '#{$var} is not a valid custom property.';
|
|
}
|
|
|
|
@if meta.type-of($opacity) != 'number' {
|
|
@error '#{$opacity} is not a valid number.';
|
|
}
|
|
|
|
$fallback: var.fallback($var);
|
|
// var(--foo-color-rgb, 31,31,31)
|
|
$var-rgb: var.create('#{var.name($var)}-rgb', hex-to-rgb($fallback));
|
|
@return string.unquote('rgb(#{$var-rgb}, #{$opacity})');
|
|
}
|
|
|
|
$_hex: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' 'a' 'b' 'c' 'd' 'e' 'f';
|
|
|
|
/// @example - scss
|
|
/// @debug _hex-to-dec('f8'); // 248
|
|
/// @param {String} $string - Hex number in string format.
|
|
/// @return {Number} Returns decimal number for given hex number.
|
|
@function _hex-to-dec($string) {
|
|
$string: string.to-lower-case($string);
|
|
$length: string.length($string);
|
|
|
|
$dec: 0;
|
|
@for $i from 1 through $length {
|
|
$factor: 1 + (15 * ($length - $i));
|
|
$index: list.index($_hex, string.slice($string, $i, $i));
|
|
$dec: $dec + $factor * ($index - 1);
|
|
}
|
|
|
|
@return $dec;
|
|
}
|
|
|
|
/// @example - scss
|
|
/// @debug hex-to-rgb('#8ab4f8'); // 138, 180, 248
|
|
/// @param {String} $string - CSS hex color in string format including '#'.
|
|
/// @return {String} Returns comma separated rgb values in string format.
|
|
@function hex-to-rgb($string) {
|
|
@if not string-ext.has-prefix($string, '#') {
|
|
@error '#{$string} is not in CSS hex color format.';
|
|
}
|
|
|
|
$string-lower: string.to-lower-case($string);
|
|
$r: '';
|
|
$g: '';
|
|
$b: '';
|
|
$length: string.length($string);
|
|
$max: if($length == 4, 1, 2);
|
|
|
|
// Check for length accuracy
|
|
@if $length != 4 and $length != 7 {
|
|
@return $string;
|
|
}
|
|
|
|
// Loop from the second character (omitting #)
|
|
@for $i from 2 through $length {
|
|
$c: string.slice($string-lower, $i, $i);
|
|
|
|
// If wrong character, return
|
|
@if list.index($_hex, $c) == null {
|
|
@return $string;
|
|
}
|
|
|
|
@if string.length($r) < $max {
|
|
$r: $r + $c;
|
|
} @else if string.length($g) < $max {
|
|
$g: $g + $c;
|
|
} @else if string.length($b) < $max {
|
|
$b: $b + $c;
|
|
}
|
|
}
|
|
|
|
@if $length == 4 {
|
|
$r: $r + $r;
|
|
$g: $g + $g;
|
|
$b: $b + $b;
|
|
}
|
|
|
|
@return #{_hex-to-dec($r), _hex-to-dec($g), _hex-to-dec($b)};
|
|
}
|
|
|
|
///
|
|
/// replace-as-rgba returns a map with the color key transformed to an RGBA
|
|
/// color value created by joining the color key value with the opacity key
|
|
/// value. The opacity key is removed from the map. This function is
|
|
/// non-destructive and returns a new instance of the given map. It should only
|
|
/// be used for disabled colors.
|
|
///
|
|
/// If $color is a var string then we would convert the color value to comma
|
|
/// separated rgb value.
|
|
///
|
|
/// @example
|
|
///. replace-as-rgba((
|
|
/// foo: red,
|
|
///. bar: 0.5
|
|
///. ), foo, bar) = (foo: rgba(255, 0, 0, 0.5))
|
|
/// @example
|
|
///. replace-as-rgba((
|
|
/// foo: var(--foo-color, #8ab4f8),
|
|
///. bar: 0.5
|
|
///. ), foo, bar) = (foo: rgb(var(--foo-color-rgb, 138, 180, 248), 0.5))
|
|
///
|
|
/// @param {Map} $map - the map with the given keys.
|
|
/// @param {String} $color-key - the color key in the map.
|
|
/// @param {String} $opacity-key - the opacity key in the map.
|
|
/// @return {Map} The map with the color key replaced by an RGBA representation.
|
|
@function replace-as-rgba($map, $color-key, $opacity-key) {
|
|
// Make a non-destructive copy of the map.
|
|
$out: map.merge($map, ());
|
|
|
|
$color: map.get($out, $color-key);
|
|
@if var.is-var($color) {
|
|
// TODO(b/213331407): Convert color from hex to rgba CSS color format to
|
|
// enable mixing rgb value with alpha using custom properties.
|
|
// (e.g., rgb(var(--foo-sys-color-on-surface-rgb, 31,31,31), 0.38))
|
|
// Remove once the attached bug is resolved.
|
|
$color: color-var-hex-to-rgba($color, map.get($out, $opacity-key));
|
|
} @else if meta.type-of($color) == 'color' {
|
|
$opacity: assert.is-type(map.get($out, $opacity-key), 'number');
|
|
$color: rgba($color, $opacity);
|
|
}
|
|
|
|
$out: map.set($out, $color-key, $color);
|
|
@return $out;
|
|
}
|
|
|
|
///
|
|
/// join-color-and-opacity-pairs returns a map with all given color and opacity
|
|
/// keys joined to create an RGBA color value. This function is non-destructive
|
|
/// and returns a new instance of the given map. It should only be used for
|
|
/// disabled colors.
|
|
///
|
|
/// @example
|
|
/// join-color-and-opacity-pairs((
|
|
/// foo-color: red,
|
|
/// foo-opacity: 0.2,
|
|
/// bar-color: green,
|
|
/// bar-opacity: 0.3,
|
|
/// ), (
|
|
/// (color-key: 'foo-color', opacity-key: 'foo-opacity'),
|
|
/// (color-key: 'bar-color', opacity-key: 'bar-opacity'),
|
|
/// )) = (foo-color: rgba(255, 0, 0, 0.2), bar-color: rgba(0, 255, 0, 0.3))
|
|
///
|
|
/// @param {Map} $map - the map with the values to modify.
|
|
/// @param {List<Map>} $color-opacity-key-pairs - the list of color/opacity key
|
|
/// pairs to join on the list.
|
|
/// @return {$Map} The map with the given color/opacity key pairs replaced by
|
|
/// RGBA representations.
|
|
///
|
|
@function join-color-and-opacity-pairs($map, $color-opacity-key-pairs) {
|
|
// Make a non-destructive copy of the map.
|
|
$out: map.merge($map, ());
|
|
@each $pair in $color-opacity-key-pairs {
|
|
$color-key: map.get($pair, color-key);
|
|
$opacity-key: map.get($pair, opacity-key);
|
|
$has-keys: map.has-key($out, $color-key) and
|
|
map.has-key($out, $opacity-key);
|
|
@if $has-keys {
|
|
$out: replace-as-rgba($out, $color-key, $opacity-key);
|
|
}
|
|
}
|
|
@return $out;
|
|
}
|