Elizabeth Mitchell 0a1f511ed8 chore: move and set up sass/ext folder
PiperOrigin-RevId: 826089867
2025-10-30 10:25:57 -07:00

240 lines
7.2 KiB
SCSS

//
// Copyright 2021 Google LLC
// SPDX-License-Identifier: Apache-2.0
//
// go/keep-sorted start
@use 'sass:map';
@use 'sass:meta';
@use 'sass:string';
// go/keep-sorted end
// go/keep-sorted start
@use '../../sass/ext/string_ext';
// go/keep-sorted end
/// Creates a custom property `var()` string.
///
/// @param {String} $name - The name of the custom property.
/// @param {*} $fallback [null] - Optional `var()` fallback value.
/// @return {String} A custom property `var()` string.
@function create($name, $fallback: null) {
$name: create-name($name);
@if $fallback == null {
@return var(#{$name});
}
@if is-var($fallback) {
$fallback-name: name($fallback);
$fallback-fallback: fallback($fallback);
@return var(#{$name}, create($fallback-name, $fallback-fallback));
}
@return var(#{$name}, $fallback);
}
/// Create a custom property variable name.
///
/// Providing a custom property name with `--*` will ignore the global prefix.
///
/// @example - scss
/// .foo {
/// color: var(#{var.create-name(foo)});
/// background: var(#{var.create-name(--bar)});
/// }
///
/// @example - css
/// .foo {
/// color: var(--md-foo);
/// background: var(--bar);
/// }
///
/// @param {String} $name - The name of the custom property.
/// @return {String} The full valid CSS custom property variable name.
@function create-name($name) {
@if string_ext.starts-with($name, '--') {
@return $name;
}
@return string.unquote('--md-#{$name}');
}
/// Returns the custom property variable name of `var()` string.
///
/// @throw If the value is not a custom property.
/// @param {String} $var - A custom property `var()` string.
/// @return {String} The custom property variable name.
@function name($var) {
$var: _parse-and-validate($var);
@return map.get($var, name);
}
/// Returns the fallback value of a custom property `var()` string. The value
/// may be null if the `var()` does not have a fallback value.
///
/// @example - scss
/// $fallback: var.fallback(var(--foo, var(--bar, 8px));
/// // "var(--bar, 8px)"
///
/// @throw If the value is not a custom property.
/// @param {String} $var - A custom property `var()` string.
/// @return {String} The fallback value of the `var()` string. May be null if
/// the `var()` does not have a fallback value.
@function fallback($var) {
$var: _parse-and-validate($var);
$fallback: map.get($var, fallback);
@if is-var($fallback) {
@return create(name($fallback), fallback($fallback));
}
@return $fallback;
}
/// Returns the deep fallback value of a custom property `var()` string. The
/// value may be null if the `var()` does not have a fallback value.
///
/// If a fallback value is another `var()`, this function will return the final
/// concrete value in the chain.
///
/// @example - scss
/// $fallback: var.deep-fallback(var(--foo, var(--bar, 8px));
/// // "8px"
///
/// @throw If the value is not a custom property.
/// @param {String} $var - A custom property `var()` string.
/// @return {String} The deep fallback value of the `var()` string. May be null
/// if the `var()` does not have a fallback value.
@function deep-fallback($var) {
$fallback: fallback($var);
@if is-var($fallback) {
@return deep-fallback($fallback);
}
@return $fallback;
}
/// Creates a new custom property `var()` string and returns it with the
/// specified new fallback value.
///
/// @example - scss
/// $new-var: set-fallback(var(--foo, var(--bar, 8px)), 16px);
/// // "var(--foo, 16px)"
///
/// @throw If the value is not a custom property.
/// @param {String} $var - A custom property `var()` string.
/// @param {*} $new-fallback - The new fallback value. May be null to remove a
/// value.
/// @return {String} A custom property `var()` string with the new fallback
/// value.
@function set-fallback($var, $new-fallback) {
$name: name($var);
@return create($name, $new-fallback);
}
/// Creates a new custom property `var()` string and returns it with the
/// specified new deep fallback value.
///
/// If the provided `var()` string's fallback value is another `var()`, this
/// function will set the final fallback value in the chain.
///
/// @example - scss
/// $new-var: deep-set-fallback(var(--foo, var(--bar, 8px)), 16px);
/// // "var(--foo, var(--bar, 16px))"
///
/// @throw If the value is not a custom property.
/// @param {String} $var - A custom property `var()` string.
/// @param {*} $new-fallback - The new fallback value. May be null to remove a
/// value.
/// @return {String} A custom property `var()` string with the new deep
/// fallback value.
@function deep-set-fallback($var, $new-fallback) {
$old-fallback: fallback($var);
@if is-var($old-fallback) {
$new-fallback: deep-set-fallback($old-fallback, $new-fallback);
}
@return set-fallback($var, $new-fallback);
}
/// Indicates whether or not a value is a custom property `var()` string.
///
/// @example - scss
/// $is-var: var.is-var('var(--foo)'); // true
///
/// @param {*} $var - The value to test.
/// @return {Bool} True if the value is a custom property `var()` string, or
/// false if not.
@function is-var($var) {
@return _parse($var) != null;
}
/// Indicates whether or not a value is a `var()` string.
///
/// @param {*} $var - The value to test.
/// @return {Bool} True if the value is a custom property `var()` string, or
/// false if not.
@function _is-var-string($var) {
@return meta.type-of($var) == 'string' and
string_ext.starts-with($var, 'var(');
}
/// Parses a `var()` string into a Map with `name` and `fallback` keys. This
/// function returns null if the value is invalid.
///
/// @param {*} $var - The value to parse.
/// @return {Map} A Map containing a string `name` key with the custom property
/// name and a `fallback` key with the fallback value (which may be null).
/// The returned Map itself may be null if the provided value is not valid.
@function _parse($var) {
@if meta.type-of($var) ==
'map' and
map.has-key($var, name) and
map.has-key($var, fallback)
{
@return $var;
}
@if not _is-var-string($var) {
@return null;
}
// Remove function name and parens
$var: string_ext.replace-start($var, 'var(', '');
$var: string_ext.replace-end($var, ')', '');
$name: string_ext.trim($var);
$fallback: null;
$comma: string.index($var, ',');
@if $comma != null {
$name: string_ext.trim(string.slice($var, 1, $comma - 1));
$fallback: string_ext.trim(string.slice($var, $comma + 1));
@if _is-var-string($fallback) {
$fallback: _parse($fallback);
@if $fallback == null {
// Invalid var() fallback string
@return null;
}
}
}
@if $name == '' or $fallback == '' {
@return null;
}
@return (name: $name, fallback: $fallback);
}
/// Parses a `var()` string into a Map with `name` and `fallback` keys.
///
/// @throw If the value is not a custom property.
/// @param {*} $var - The value to parse.
/// @return {Map} A Map containing a string `name` key with the custom property
/// name and a `fallback` key with the fallback value (which may be null).
@function _parse-and-validate($var) {
$var-map: _parse($var);
@if $var-map == null {
@error '"#{$var}" is not a valid var() string';
}
@return $var-map;
}