Project import generated by Copybara.

GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/node_modules/mdl-ext/src/_functions.scss b/node_modules/mdl-ext/src/_functions.scss
new file mode 100644
index 0000000..2571fec
--- /dev/null
+++ b/node_modules/mdl-ext/src/_functions.scss
@@ -0,0 +1,302 @@
+///
+/// Returns the opposite direction of each direction in a list
+/// Modified from: https://css-tricks.com/snippets/sass/opposite-direction-function/
+/// @author Hugo Giraudel
+/// @param {List} $directions - List of initial directions
+/// @return {List} - List of opposite directions
+@function mdlext-opposite-direction($directions) {
+  $opposite-directions: ();
+  $direction-map: (
+    'top':    'bottom',
+    'right':  'left',
+    'bottom': 'top',
+    'left':   'right',
+    'center': 'center',
+    'ltr':    'rtl',
+    'rtl':    'ltr'
+  );
+
+  @each $direction in $directions {
+    $direction: to-lower-case($direction);
+
+    @if map-has-key($direction-map, $direction) {
+      $opposite-directions: append($opposite-directions, unquote(map-get($direction-map, $direction)));
+    }
+    @else {
+      @warn "No opposite direction can be found for `#{$direction}`. Direction omitted.";
+    }
+  }
+
+  @return $opposite-directions;
+}
+
+///
+/// Strip unit from value
+/// @author Hugo Giraudel
+/// http://hugogiraudel.com/2013/08/12/sass-functions/
+/// https://css-tricks.com/snippets/sass/strip-unit-function/
+/// @param {Number} $number - Number to remove unit from
+/// @return {Number} - Unitless number
+
+@function strip-unit($number) {
+  @return if(type-of($number) == 'number' and not unitless($number), $number / ($number * 0 + 1), $number);
+}
+
+///
+/// Clamping a number means restricting it between min and max values.
+///    4 clamped to 1-3 equals 3.
+///   -5 clamped to 1-10 equals 1.
+///   42 clamped to 10-100 equals 42.
+/// @author Hugo Giraudel
+/// http://hugogiraudel.com/2013/08/12/sass-functions/
+/// @param {Number} $value - The value to clamp
+/// @param {Number} $min - min value in range
+/// @param {Number} $max - Max value in range
+/// @return {Number} - The clamped value
+
+@function clamp($value, $min, $max) {
+  @return if($value > $max, $max, if($value < $min, $min, $value));
+}
+
+///
+/// Convert one unit into another
+/// @author Hugo Giraudel
+/// http://www.sitepoint.com/understanding-sass-units/
+/// @param {Number} $value - Initial value
+/// @param {String} $unit - Desired unit
+/// @return {Number}
+/// @throw Error if `$unit` does not exist or if units are incompatible.
+
+/* stylelint-disable */
+@function convert-unit($value, $unit) {
+  $units: (
+    'px'  : 0px,
+    'cm'  : 0cm,
+    'mm'  : 0mm,
+    '%'   : 0%,
+    'ch'  : 0ch,
+    'in'  : 0in,
+    'em'  : 0em,
+    'rem' : 0rem,
+    'pt'  : 0pt,
+    'pc'  : 0pc,
+    'ex'  : 0ex,
+    'vw'  : 0vw,
+    'vh'  : 0vh,
+    'vmin': 0vmin,
+    'vmax': 0vmax,
+    'deg' : 0deg,
+    'turn': 0turn,
+    'rad' : 0rad,
+    'grad': 0grad,
+    's'   : 0s,
+    'ms'  : 0ms,
+    'Hz'  : 0Hz,
+    'kHz' : 0kHz,
+    'dppx': 0dppx,
+    'dpcm': 0dpcm,
+    'dpi' : 0dpi,
+  );
+
+  @if map-has-key($units, $unit) {
+    @return map-get($units, $unit) + $value;
+  }
+
+  @error "Unknown unit `#{$unit}`.";
+}
+/* stylelint-enable */
+
+
+///
+/// Replace `$search` with `$replace` in `$string`
+/// @author Hugo Giraudel, http://hugogiraudel.com/2014/01/13/sass-string-replacement-function/
+/// @param {String} $string - Initial string
+/// @param {String} $search - Substring to replace
+/// @param {String} $replace ('') - New value
+/// @return {String} - Updated string
+@function str-replace($string, $search, $replace: '') {
+  $index: str-index($string, $search);
+
+  @if $index {
+    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
+  }
+  @return $string;
+}
+
+///
+/// @function explode() -- split a string into a list of strings
+/// @author https://gist.github.com/danielpchen/3677421ea15dcf2579ff
+///  {string} $string: the string to be split
+///  {string} $delimiter: the boundary string
+///  @return {list} the result list
+@function explode($string, $delimiter: ',') {
+  $result: ();
+  @if $delimiter == "" {
+    @for $i from 1 through str-length($string) {
+      $result: append($result, str-slice($string, $i, $i));
+    }
+    @return $result;
+  }
+  $exploding: true;
+  @while $exploding {
+    $d-index: str-index($string, $delimiter);
+    @if $d-index {
+      @if $d-index > 1 {
+        $result: append($result, str-slice($string, 1, $d-index - 1));
+        $string: str-slice($string, $d-index + str-length($delimiter));
+      }
+      @else if $d-index == 1 {
+        $string: str-slice($string, 1, $d-index + str-length($delimiter));
+      }
+      @else {
+        $result: append($result, $string);
+        $exploding: false;
+      }
+    }
+    @else {
+      $result: append($result, $string);
+      $exploding: false;
+    }
+  }
+  @return $result;
+}
+
+///
+/// Add `$unit` to `$value`
+/// @author Hugo Giraudel
+///
+/// @param {Number} $value - Value to add unit to
+/// @param {String} $unit - String representation of the unit
+///
+/// @return {Number} - `$value` expressed in `$unit`
+/// @throw Error if `$unit` does not exist or if units are incompatible.
+///
+@function to-length($value, $unit) {
+  $units: (
+    'px'  : 1px,
+    'cm'  : 1cm,
+    'mm'  : 1mm,
+    '%'   : 1%,
+    'ch'  : 1ch,
+    'pc'  : 1pc,
+    'in'  : 1in,
+    'em'  : 1em,
+    'rem' : 1rem,
+    'pt'  : 1pt,
+    'ex'  : 1ex,
+    'vw'  : 1vw,
+    'vh'  : 1vh,
+    'vmin': 1vmin,
+    'vmax': 1vmax
+  );
+
+  @if not index(map-keys($units), $unit) {
+    @error('Invalid unit `#{$unit}`.');
+  }
+
+  @return $value * map-get($units, $unit);
+}
+
+///
+/// Casts a string into a number
+///
+/// @author Hugo Giraudel
+// @param {String | Number} $value - Value to be parsed
+///
+/// @return {Number}
+/// @throw Error if `$value` is not a number or a string.
+///
+@function to-number($value) {
+  @if type-of($value) == 'number' {
+    @return $value;
+  }
+  @else if type-of($value) != 'string' {
+    @error('Value for `to-number` should be a number or a string.');
+  }
+
+  $result: 0;
+  $digits: 0;
+  $minus: str-slice($value, 1, 1) == '-';
+  $numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9);
+
+  @for $i from if($minus, 2, 1) through str-length($value) {
+    $character: str-slice($value, $i, $i);
+
+    @if not (index(map-keys($numbers), $character) or $character == '.') {
+      @return to-length(if($minus, -$result, $result), str-slice($value, $i));
+    }
+
+    @if $character == '.' {
+      $digits: 1;
+    }
+    @else if $digits == 0 {
+      $result: $result * 10 + map-get($numbers, $character);
+    }
+    @else {
+      $digits: $digits * 10;
+      $result: $result + map-get($numbers, $character) / $digits;
+    }
+  }
+
+  @return if($minus, -$result, $result);
+}
+
+///
+/// Convert `$rgb-string` to a number list
+/// @author Leif Olsen
+/// @param {String | Number} $value - Value to be parsed
+/// @return {list} the rgb number list
+/// @throw Error if `$value` is not a number, color or a string.
+@function rgb-string-to-numbers($value) {
+  @if type-of($value) == 'number' or type-of($value) == 'color' {
+    @return $value;
+  }
+  @else if type-of($value) != 'string' {
+    @error('Value for `rgb-string-to-numbers` should be a number or a string.');
+  }
+
+  $s: str-replace($value, "rgba");
+  $s: str-replace($s, "rgb");
+  $s: str-replace($s, "(");
+  $s: str-replace($s, ")");
+  $s: str-replace($s, " ");
+  $l: explode($s);
+  $result: ();
+  @for $i from 1 through length($l) {
+    $result: append($result, to-number(nth($l, $i)));
+  }
+  @return $result;
+}
+
+///
+/// Convert `$rgb-string` to a corresponding hex value
+/// @author Leif Olsen
+/// @param {String | Number} $value - Value to be parsed
+/// @return {number} the rgb hex value
+/// @throw Error if `$value` is not a number, color or a string.
+@function rgb-string-to-hex($value) {
+  @if type-of($value) == 'number' or type-of($value) == 'color' {
+    @return $value;
+  }
+  @else if type-of($value) != 'string' {
+    @error('Value for `rgb-string-to-numbers` should be a number or a string.');
+  }
+  $l: rgb-string-to-numbers($value);
+  @return rgb(nth($l, 1), nth($l, 2), nth($l, 3));
+}
+
+
+///
+/// Convert hex color to a coresponding `$rgb-string`
+/// @author https://github.com/google/material-design-lite/issues/1689
+/// @param {Number} $hexColor - Value to convert
+/// @return {String} the rgb string value
+///
+/// @example - $color-primary: hex-to-string(#333);
+@function hex-to-rgb-string($hexColor) {
+  // 0.999999 val in alpha actually compiles to 1.0
+  $rgbaVal:  inspect(rgba($hexColor, 0.9999999));
+
+  // slice substring between 'rgba(' and '1.0)'
+  @return str-slice($rgbaVal, 6, str-length($rgbaVal)-4);
+}