Source: breakpoints.scss

/**
 * @namespace Breakpoints
 */



@use 'sass:meta';
@use 'sass:list';
@use 'sass:map';

@use 'globals' as *;
@use 'util';



$jig---auto-breakpoint: list.nth(map.keys($jig---breakpoint-config), 1);



/**
 * @namespace Breakpoints:get-auto-breakpoint
 */

/**
 * Returns the current auto breakpoint value.
 *
 * @memberof Breakpoints:get-auto-breakpoint
 * @function
 * @name get-auto-breakpoint
 * @alias get-auto-breakpoint
 *
 * @returns {String} the name of the current named auto breakpoint
 *
 * @see set-auto-breakpoint
 * @see reset-auto-breakpoint
 *
 * @example
 * get-auto-breakpoint()
 *   => 'medium'
 */
@function get-auto-breakpoint(){
	@return $jig---auto-breakpoint;
}



/**
 * @namespace Breakpoints:set-auto-breakpoint
 */

/**
 * Sets the auto breakpoint to a named breakpoint value.
 * Hint: in Sass we do _not_ have to do this manually, if we want to use auto breakpoint values,
 * since blocks are always evaluated _after_ the block mixin around the block, which results
 * in the block knowing the breakpoint value automatically from the mixin around it.
 *
 * @memberof Breakpoints:set-auto-breakpoint
 * @function
 * @name set-auto-breakpoint
 * @alias set-auto-breakpoint
 *
 * @param {String} $breakpoint - a named breakpoint defined in the jig config
 * @throws error if breakpoint is unknown
 *
 * @see reset-auto-breakpoint

 * @example
 * \@include set-auto-breakpoint(medium);
 * \@include breakpoint(medium){
 *   ...
 * }
 */
@mixin set-auto-breakpoint($breakpoint){
	@if map.has-key($jig---breakpoint-config, $breakpoint) {
		$jig---auto-breakpoint: $breakpoint !global;
	} @else {
		@error 'jig:set-current-breakpoint | unknown named breakpoint "#{$breakpoint}"';
	}
}



/**
 * @namespace Breakpoints:reset-auto-breakpoint
 */

/**
 * Resets the auto breakpoint to the first/smallest named breakpoint defined in the jig config.
 * Hint: this is automatically called at the end of the breakpoint mixin, so usually you should be fine
 * never calling this manually
 *
 * @memberof Breakpoints:reset-auto-breakpoint
 * @function
 * @name reset-auto-breakpoint
 * @alias reset-auto-breakpoint
 *
 * @see set-auto-breakpoint

 * @example
 * \@include reset-auto-breakpoint();
 */
@mixin reset-auto-breakpoint(){
	$jig---auto-breakpoint: list.nth(map.keys($jig---breakpoint-config), 1) !global;
}



/**
 * @namespace Breakpoints:is-named-breakpoint
 */

/**
 * Returns if the given breakpoint is a registered named breakpoint to be found in the jig config.
 *
 * @memberof Breakpoints:is-named-breakpoint
 * @function
 * @name is-named-breakpoint
 * @alias is-named-breakpoint
 *
 * @param {String} $breakpoint - a named breakpoint defined in the jig config
 * @returns {Boolean} true if breakpoint is a registered named breakpoint name
 *
 * @example
 * is-named-breakpoint(medium)
 *   => true
 */
@function is-named-breakpoint($breakpoint){
	@return map.has-key($jig---breakpoint-config, $breakpoint);
}



/**
 * @namespace Breakpoints:build-breakpoint-range
 */

/**
 * Returns a string to be used in a media query, which defines the range/bounds of a breakpoint with
 * min and/or max value.
 *
 * @memberof Breakpoints:build-breakpoint-range
 * @function
 * @name build-breakpoint-range
 * @alias build-breakpoint-range
 *
 * @param {?Number} [$min=null] - the min width of the breakpoint
 * @param {?Number} [$max=null] - the max width of the breakpoint
 * @returns {String} the media query string for the breakpoint range
 *
 * @example
 * build-breakpoint-range(0, 767px)
 *   => '(min-width: 0) and (max-width: 767px)'
 * build-breakpoint-range(null, 100rem)
 *   => '(max-width: 100rem)'
 */
@function build-breakpoint-range($min:null, $max:null){
	@return util.str-join(
		[
			if($min != null, '(min-width: #{$min})', null),
			if($max != null, '(max-width: #{$max})', null)
		],
		' and '
	);
}



/**
 * @namespace Breakpoints:build-breakpoint-query
 */

/**
 * Constructs a query to be used in a media query, based on a breakpoint definition.
 * Also automatically converts values to rem.
 *
 * Directions in composite definitions may be "up", "down" or "only".
 *
 * You may also define the special breakpoints "landscape" or "portrait" to cover device orientations.
 *
 * @memberof Breakpoints:build-breakpoint-query
 * @function
 * @name build-breakpoint-query
 * @alias build-breakpoint-query
 *
 * @param {?Number|Literal|List<String>} [$breakpoint-definition=0] - either a simple number or a composite definition of width and direction, where the width may either be a number or a name defined in the named breakpoints
 * @returns {String} the media query string for the breakpoint definition
 * @throws error if named breakpoint is unknown
 * @throws error if an unnamed breakpoint has an "only" direction
 *
 * @example
 * build-breakpoint-query(200rem)
 *   => '(min-width: 200rem)'
 * build-breakpoint-query(small down)
 *   => '(max-width: 199rem)'
 * build-breakpoint-query(('large' 'only'))
 *   => '(min-width: 200rem) and (max-width: 499rem)'
 * build-breakpoint-query(1024px only)
 *   => '(min-width: 64rem) and (max-width: 64rem)'
 * build-breakpoint-query(landscape)
 *   => '(orientation: landscape)'
 */
@function build-breakpoint-query($breakpoint-definition:0){
	$breakpoint: if($breakpoint-definition and (list.length($breakpoint-definition) > 0), list.nth($breakpoint-definition, 1), 0);
	$direction: if($breakpoint-definition and (list.length($breakpoint-definition) > 1), list.nth($breakpoint-definition, 2), 'up');
	$breakpoint-name: null;
	$next-breakpoint: null;
	$min: null;
	$max: null;
	$query-em-conversion-base: 16px; // this is always 16px, no matter what is defined on <html>

	@if $breakpoint == 'overwrite' {
		@return '(min-width: 0)';
	} @else if ($breakpoint == 'landscape') or ($breakpoint == 'portrait') {
		@return '(orientation: #{$breakpoint})';
	} @else if meta.type-of($breakpoint) == 'string' {
		@if is-named-breakpoint($breakpoint) {
			$breakpoint-name: $breakpoint;
			$breakpoint: map.get($jig---breakpoint-config, $breakpoint-name);
			$next-breakpoint: util.map-next($jig---breakpoint-config, $breakpoint-name);
		} @else {
			@error 'jig:build-breakpoint-query | "#{$breakpoint-definition}" is not a defined breakpoint';
		}
	}

	@if ($breakpoint-name == null) and ($direction == 'only') {
		@error 'jig:build-breakpoint-query | only named media queries can have an "only" range';
	}

	// we are building media queries with em instead of rem and px
	// why? => https://zellwk.com/blog/media-query-units/

	@if ($direction == 'only') or ($direction == 'up') {
		$min: util.to-em($breakpoint, $query-em-conversion-base);
	}

	@if ($direction == 'only') or ($direction == 'down') {
		@if $breakpoint-name == null {
			$max: util.to-em($breakpoint, $query-em-conversion-base);
		} @else if $next-breakpoint != null {
			$max: util.to-em($next-breakpoint, $query-em-conversion-base) - util.to-em(1px, $query-em-conversion-base);
		}
	}

	@if ($min == 0) and ($max == null){
		$min: null;
	}

	@return build-breakpoint-range($min, $max);
}



/**
 * @namespace Breakpoints:breakpoint
 */

/**
 * Renders media queries based one one or more breakpoint definitions.
 *
 * @memberof Breakpoints:breakpoint
 * @function
 * @name breakpoint
 * @alias breakpoint
 *
 * @param {Number|Literal|List<String>|List<Literal>|List<List<String>>} $breakpoint-definitions - a list of breakpoint definitions according to build-breakpoint-query
 *
 * @example
 * \@include breakpoint(small){
 *   ...
 * }
 * \@include breakpoint(small down, large up){
 *   ...
 * }
 */
@mixin breakpoint($breakpoint-definitions...){
	@each $breakpoint-definition in $breakpoint-definitions {
		$query: build-breakpoint-query($breakpoint-definition);
		$breakpoint: if(list.length($breakpoint-definition) > 0, list.nth($breakpoint-definition, 1), 0);
		$direction: if(list.length($breakpoint-definition) > 1, list.nth($breakpoint-definition, 2), 'up');
		$breakpoint-index: index(map.keys($jig---breakpoint-config), list.nth($breakpoint-definition, 1));
		$print-breakpoint-index: list.index(map.keys($jig---breakpoint-config), $jig---print-breakpoint);

		// set current breakpoint var to mixin breakpoint value to allow for auto-evaluation inside
		@if is-named-breakpoint($breakpoint){
			@include set-auto-breakpoint($breakpoint);
		}

		@if $query == '' {
			@content;
		} @else {
			@if(
				($breakpoint-index != null)
				and (
					($breakpoint-index <= $print-breakpoint-index)
					or ($direction == 'down')
				)
			){
				@media print, screen and #{$query} {
					@content;
				}
			} @else {
				@media screen and #{$query} {
					@content;
				}
			}
		}

		// restore initial value after mixin has been rendered
		@include reset-auto-breakpoint();
	}
}



/**
 * @namespace Breakpoints:breakpoint-value
 */

/**
 * Search for a value, defined for a breakpoint, in a given map of values.
 * The function escalates in a mobile-first manner. So we take the value for the smallest breakpoint
 * and step up the breakpoints one by one until we reach the defined breakpoint. So, if we want the
 * according value for "large", but we only have a value for "medium", we'll get the "medium" value, which,
 * in mobile-first manner, escalates upwards and is the "large" value if nothing else is defined.
 *
 * @memberof Breakpoints:breakpoint-value
 * @function
 * @name breakpoint-value
 * @alias breakpoint-value
 *
 * @param {*|Map} $value - a map of breakpoint-keyed map of values, or a simple value
 * @param {Literal|String} $breakpoint - either "auto" (to use the current breakpoint) or one of the defined named breakpoints
 * @returns {*|null} the breakpoint value or null if nothing was found
 * @throws error if named breakpoint is unknown
 *
 * @example
 * breakpoint-value(
 *   (
 *     'small' : 10px,
 *     'medium' : 20px
 *   ),
 *   large
 * )
 *   => 20px
 */
@function breakpoint-value($value, $breakpoint:'auto'){
	@if ($breakpoint != 'auto') and not map.has-key($jig---breakpoint-config, $breakpoint) {
		@error 'jig:breakpoint-value | given breakpoint "#{$breakpoint}" not defined';
	}

	@if meta.type-of($value) == 'map' {
		$res: null;

		@if $breakpoint == 'auto' {
			$breakpoint: get-auto-breakpoint();
		}

		@each $breakpoint-name, $breakpoint-definition in $jig---breakpoint-config {
			$breakpoint-value: map.get($value, $breakpoint-name);

			@if $breakpoint-value != null {
				$res: $breakpoint-value;
			}

			@if $breakpoint-name == $breakpoint {
				@return $res;
			}
		}

		@return null;
	} @else {
		@return $value;
	}
}



/**
 * @namespace Breakpoints:attributes-for-breakpoints
 */

/**
 * Renders attribute values for given attributes for defined breakpoints.
 *
 * Definitions will be rendered together if possible, minimizing the amount of media queries.
 * However, each call of this mixin will, most likely, render multiple media queries, so keep a close eye
 * on your media query structure to avoid unnecessarily doubled definitions and keep media queries to a minimum.
 * If in doubt, it might be a better idea to write the queries manually, perhaps rather using `map.get` or
 * `breakpoint-value` to automatically pull values from breakpoint value maps.
 *
 * @memberof Breakpoints:attributes-for-breakpoints
 * @function
 * @name attributes-for-breakpoints
 * @alias attributes-for-breakpoints
 *
 * @see attribute-for-breakpoints
 *
 * @param {Map} $attributes - keys are attribute names, while values are either plain values or maps with breakpoint name keys, providing different values per breakpoint
 * @param {Number} [$factor=null] - if a float factor is provided all values will be multiplied with this factor
 *
 * @example
 * \@include attributes-for-breakpoints(
 *   (
 *     'font-size' : 12px,
 *     'line-height' : (
 *       'small' : 1,
 *       'large' : 1.25
 *     ),
 *     'margin-top' : (
 *       'small' : 10px,
 *       'medium' : 20px
 *     )
 *   ),
 *   2.0
 * );
 */
@mixin attributes-for-breakpoints($attributes, $factor:null){
	$attributes-for-breakpoints: ();
	@each $attribute-name, $attribute-value in $attributes {
		@if meta.type-of($attribute-value) != 'map' {
			@if $factor == null {
				#{$attribute-name}: $attribute-value;
			} @else {
				#{$attribute-name}: ($factor * $attribute-value);
			}
		} @else {
			@each $breakpoint-name, $breakpoint-definition in $jig---breakpoint-config {
				$breakpoint-value: map.get($attribute-value, $breakpoint-name);
				@if $breakpoint-value != null {
					$breakpoint-attributes: map.get($attributes-for-breakpoints, $breakpoint-name);
					@if $breakpoint-attributes == null {
						$breakpoint-attributes: ();
					}

					$breakpoint-attributes: map.merge(
						$breakpoint-attributes,
						($attribute-name : $breakpoint-value)
					);

					$attributes-for-breakpoints: map.merge(
						$attributes-for-breakpoints,
						($breakpoint-name : $breakpoint-attributes)
					);
				}
			}
		}
	}

	@each $breakpoint-name, $breakpoint-definition in $jig---breakpoint-config {
		$breakpoint-attributes: map.get($attributes-for-breakpoints, $breakpoint-name);
		@if ($breakpoint-attributes != null) and (list.length(map.keys($breakpoint-attributes)) > 0) {
			@include breakpoint($breakpoint-name){
				@each $attribute-name, $attribute-value in $breakpoint-attributes {
					@if $factor == null {
						#{$attribute-name}: $attribute-value;
					} @else {
						#{$attribute-name}: ($factor * $attribute-value);
					}
				}
			}
		}
	}
}



/**
 * @namespace Breakpoints:attribute-for-breakpoints
 */

/**
 * Renders attribute values for given attribute for defined breakpoints.
 *
 * This is the single attribute version of `attributes-for-breakpoints`.
 * Since this version does not optimize the usage of media queries, please make sure to only use this mixin,
 * if you'll definitely only have one attribute to be defined in multiple breakpoints.
 *
 * @memberof Breakpoints:attribute-for-breakpoints
 * @function
 * @name attribute-for-breakpoints
 * @alias attribute-for-breakpoints
 *
 * @see attributes-for-breakpoints
 *
 * @param {String} $attribute - the name of the attribute you want to set
 * @param {*} $value - the value to set the attribute to
 * @param {Number} [$factor=null] - if a float factor is provided the value will be multiplied with this factor
 *
 * @example
 * \@include attribute-for-breakpoints(
 *   'line-height',
 *   (
 *     'small' : 1,
 *     'large' : 1.25
 *   ),
 *   1.0
 * );
 */
@mixin attribute-for-breakpoints($attribute, $value, $factor:null){
	$attributes: ();
	$attributes: map.merge($attributes, ('#{$attribute}' : $value));
	@include attributes-for-breakpoints($attributes, $factor);
}



/**
 * @namespace Breakpoints:overwrite-breakpoint-for-attributes
 */

/**
 * Use this, if you need to overwrite attribute values previously defined in (a) breakpoint(s).
 *
 * A use case might be, for example, to set a font-size to a static value in an element with a responsive,
 * breakpoint-based font-size definition.
 *
 * @memberof Breakpoints:overwrite-breakpoint-for-attributes
 * @function
 * @name overwrite-breakpoint-for-attributes
 * @alias overwrite-breakpoint-for-attributes
 *
 * @param {Map} $attributes - keys are attribute names, while values are either plain values or maps with breakpoint name keys, providing different values per breakpoint
 * @param {Number} [$factor=null] - if a float factor is provided all values will be multiplied with this factor
 *
 * @see overwrite-breakpoint-for-attribute
 *
 * @example
 * \@include overwrite-breakpoint-for-attributes(
 *   (
 *     'font-size' : 12px,
 *     'line-height' : 1.25
 *     'margin-top' : 20px
 *   ),
 *   2.0
 * );
 */
@mixin overwrite-breakpoint-for-attributes($attributes, $factor:null){
	@include breakpoint('overwrite'){
		@each $attribute-name, $attribute-value in $attributes {
			@if $factor == null {
				#{$attribute-name}: $attribute-value;
			} @else {
				#{$attribute-name}: ($factor * $attribute-value);
			}
		}
	}
}



/**
 * @namespace Breakpoints:overwrite-breakpoint-for-attribute
 */

/**
 * Use this, if you need to overwrite an attribut value previously defined in (a) breakpoint(s).
 *
 * A use case might be, for example, to set a font-size to a static value in an element with a responsive,
 * breakpoint-based font-size definition.
 *
 * @memberof Breakpoints:overwrite-breakpoint-for-attribute
 * @function
 * @name overwrite-breakpoint-for-attribute
 * @alias overwrite-breakpoint-for-attribute
 *
 * @see overwrite-breakpoint-for-attributes
 *
 * @param {String} $attribute - the name of the attribute you want to set
 * @param {*} $value - the value to set the attribute to
 * @param {Number} [$factor=null] - if a float factor is provided the value will be multiplied with this factor
 *
 * @example
 * \@include overwrite-breakpoint-for-attribute(font-size, 12px, 2.0);
 */
@mixin overwrite-breakpoint-for-attribute($attribute, $value, $factor:null){
	$attributes: ();
	$attributes: map.merge($attributes, ('#{$attribute}' : $value));
	@include overwrite-breakpoint-for-attributes($attributes, $factor);
}



/**
 * @namespace Breakpoints:overwrite-breakpoint
 */

/**
 * Use this, if you need to overwrite something previously defined in (a) breakpoint(s).
 *
 * A use case might be, for example, to redefine something statically in an override situation, which has
 * been defined responsively before.
 *
 * @memberof Breakpoints:overwrite-breakpoint
 * @function
 * @name overwrite-breakpoint
 * @alias overwrite-breakpoint
 *
 * @example
 * \@include overwrite-breakpoint(){
 *   font-size: 12xp;
 *   margin-top: 20px;
 * }
 */
@mixin overwrite-breakpoint(){
	@include breakpoint('overwrite'){
		@content;
	}
}