_map-ext.scss 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //
  2. // Copyright 2021 Google Inc.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. @use 'sass:list';
  23. @use 'sass:map';
  24. // A collection of extensions to the sass:map module
  25. // https://sass-lang.com/documentation/modules/map
  26. /// Splits a Map into two separate Maps: one without the provided keys and one
  27. /// exclusively with the provided keys.
  28. ///
  29. /// @example - scss
  30. /// $map: (
  31. /// focus: blue,
  32. /// focus-within: blue,
  33. /// hover: teal,
  34. /// active: green,
  35. /// );
  36. ///
  37. /// $pair: split($map, focus, focus-within);
  38. /// // (
  39. /// // (hover: teal, active: green),
  40. /// // (focus: blue, focus-within: blue)
  41. /// // );
  42. ///
  43. /// @param {Map} $map - The Map to split.
  44. /// @param {String...} $keys - Keys to split the Map by.
  45. /// @return {List} A List pair with two new Maps: the first with the keys
  46. /// removed and the second exclusively with the keys.
  47. @function split($map, $keys...) {
  48. $map1: ();
  49. $map2: ();
  50. @each $key, $value in $map {
  51. @if list.index($keys, $key) {
  52. $map2: map.set($map2, $key, $value);
  53. } @else {
  54. $map1: map.set($map1, $key, $value);
  55. }
  56. }
  57. @return ($map1, $map2);
  58. }
  59. /// Picks provided keys from a Map.
  60. ///
  61. /// @example - scss
  62. /// $map: (
  63. /// focus: blue,
  64. /// focus-within: blue,
  65. /// hover: teal,
  66. /// active: green,
  67. /// );
  68. ///
  69. /// pick($map, hover, active);
  70. /// // (hover: teal, active: green),
  71. ///
  72. /// pick($map, (hover, active)...);
  73. /// // (hover: teal, active: green),
  74. ///
  75. /// @param {Map} $map - The Map to pick.
  76. /// @param {String...} $keys - Keys to pick from the Map.
  77. /// @return {List} Map with only the keys provided.
  78. @function pick($map, $keys...) {
  79. @return list.nth(split($map, $keys...), 2);
  80. }
  81. ///
  82. /// trim-keys returns the given map with any matching keys removed.
  83. ///
  84. /// @example
  85. /// trim-keys(('foo': red, 'bar': 5), ('foo')) = ('bar': 5)
  86. ///
  87. /// @param {Map} $map - the map to rename.
  88. /// @param {List} $keys - the key names to trim off.
  89. /// @return {Map} the $map with any matching keys removed.
  90. ///
  91. @function trim-keys($map, $keys) {
  92. $out: map.merge($map, ());
  93. @each $key, $value in $map {
  94. @if list.index($keys, $key) {
  95. $out: map.remove($out, $key);
  96. }
  97. }
  98. @return $out;
  99. }
  100. ///
  101. /// rename-keys returns the given map with any matching keys renamed to the
  102. /// given name.
  103. ///
  104. /// @example
  105. /// rename-keys(('foo': red), ('foo': 'bar')) = ('bar': red)
  106. ///
  107. /// @param {Map} $map - the map to rename.
  108. /// @param {Map} $rename - the renames to apply.
  109. /// @return {Map} the $map with any matching keys renamed per $rename.
  110. ///
  111. @function rename-keys($map, $rename) {
  112. $out: trim-keys($map, map.keys($rename));
  113. @each $from, $to in $rename {
  114. @if map.has-key($map, $from) {
  115. $out: map.set($out, $to, map.get($map, $from));
  116. }
  117. }
  118. @return $out;
  119. }
  120. /// Useful to avoid typos in the key string when accessing a map where the
  121. /// key is expected to exist.
  122. ///
  123. /// @param {Map} $map - the map that contains the key.
  124. /// @param {String} $key - the key the value of which we want to retrieve.
  125. @function map-get-or-err($map, $key) {
  126. @if not map.has-key($map, $key) {
  127. @error 'Key #{$key} expected but not found in argument map.';
  128. }
  129. @return map.get($map, $key);
  130. }