/*!
	yeah-grid-utils

	
	@version	1.2.1
	@author		Yeah <https://github.com/yeah8000>
	@used		https://grid-utils.yeah.de
*/

/**
 * Defaults
 */

$wide-screen: 1920px !default;

//define your breakpoints
$breakpoints: (
	xs: 320px,
	md: 768px,
	lg: 1024px,
	xl: 1920px 1080px
) !default;

//define how your grid behaves onn these breakpoints
$grid-sizes: (
	xs: (
		gutter-width: 10px,
		outer-margin: 15px,
		max-width: 500px
	),
	md: (
		gutter-width: 20px,
		outer-margin: 40px,
		max-width: 950px
	),
	lg: (
		gutter-width: 30px,
		outer-margin: 80px,
		max-width: 1200px
	),
	xl: (
		gutter-width: 60px,
		outer-margin: 100px,
		max-width: 1400px
	)
) !default;

/**
 * Opinions
 */

*,
*:before,
*:after {
	box-sizing: border-box;
}

/**
 * Mixins and functions
 */

/**
 * mobile-first media query at breakpoint
 * @param  {cssunit} $size	breakpoint in pixels or slug (see $breakpoints) or map of width/height
 * @param  {cssunit} $height breakpoint in pixels
 */
@mixin at($size) {
	$height: false;

	// $size is probably $width
	@if type-of($size) == string {
		$size: map-get($breakpoints, $size);
	}

	// but $size may still be a list of width and height as well
	@if length($size) == 2 {
		$height: nth($size, 2);
		$size: nth($size, 1);
	}

	// by now $size is definitely the width
	@if $height {
		@media only screen and (min-width: $size) and (min-height: $height) {
			@content;
		}
	} @else {
		@media only screen and (min-width: $size) {
			@content;
		}
	}
}

/**
 * mobile-last media query at breakpoint
 * @param  {cssunit} $size	breakpoint in pixels or slug (see $breakpoints) or map of width/height
 * @param  {cssunit} $height breakpoint in pixels
 */
@mixin until($size) {
	$height: false;

	// $size is probably $width
	@if type-of($size) == string {
		$size: map-get($breakpoints, $size);
	}

	// but $size may still be a list of width and height as well
	@if length($size) == 2 {
		$height: nth($size, 2);
		$size: nth($size, 1);
	}

	@if $height {
		@media only screen and (max-width: ($size - 1px)), screen and (max-height: ($height - 1px)) {
			@content;
		}
	} @else {
		@media only screen and (max-width: ($size - 1px)) {
			@content;
		}
	}
}

/**
 * shorthand: set the gutter-width as value for a property
 */

@mixin gutter-width-as($property, $modifier: 1) {
	@include map-grid-values(
		(
			$property: (
				'gutter-width',
				$modifier
			)
		)
	);
}

/**
 * shorthand: set the outer-margin as value for a property
 */

@mixin outer-margin-as($property, $modifier: 1) {
	@include map-grid-values(
		(
			$property: (
				'outer-margin',
				$modifier
			)
		)
	);
}

/**
 * shorthand: set the gutter-width as value for a property
 */

@mixin max-width-as($property, $modifier: 1) {
	@include map-grid-values(
		(
			$property: (
				'max-width',
				$modifier
			)
		)
	);
}

/**
 * shorthand: get the value of a property at a certain size
 */

@function value-at($value, $size, $modifier: 1) {
	@return $modifier * map-get(map-get($grid-sizes, $size), $value);
}

/**
 * Get breakpoint by name
 * @param  {string} $name
 */
@function breakpoint($name) {
	@return map-get($breakpoints, $name);
}

/**
 * utility mixin for containers
 */
@mixin container() {
	margin-right: auto;
	margin-left: auto;
	width: 100%;
	@include map-grid-values(
		(
			'padding-right': (
				'outer-margin'
			),
			'padding-left': (
				'outer-margin'
			),
			'max-width': (
				'max-width'
			)
		)
	);
}

/**
 * utility mixin for fullwidth containers
 */
@mixin container-full() {
	margin-right: auto;
	margin-left: auto;
	width: 100%;
	max-width: $wide-screen;
	@include map-grid-values(
		(
			'padding-right': (
				'outer-margin'
			),
			'padding-left': (
				'outer-margin'
			)
		)
	);
}

/**
 * utility mixin for containers
 */
@mixin grid() {
	width: 100%;
	display: grid;
}

/**
 * utility mixin for rows that ignore the outer-margin
 */
@mixin grid-full() {
	width: auto;
	@include map-grid-values(
		(
			'margin-right': (
				'outer-margin',
				-1
			),
			'margin-left': (
				'outer-margin',
				-1
			)
		)
	);
}

/**
 * utility mixin for getting grid vars as css variables
 */
@mixin grid-vars-to-css-vars() {
	@include map-grid-values(
		(
			'--outer-margin': (
				'outer-margin'
			),
			'--gutter-width': (
				'gutter-width'
			),
			'--max-width': (
				'max-width'
			)
		)
	);
}

/**
 * split a string by a seperator
 * thanks: https://stackoverflow.com/questions/32376461/how-to-split-a-string-into-two-lists-of-numbers-in-sass
 */
@function str-split($string, $separator) {
	$split-arr: ();
	$index: str-index($string, $separator);
	// loop through string
	@while $index != null {
		// get the substring from the first character to the separator
		$item: str-slice($string, 1, $index - 1);
		// push item to array
		$split-arr: append($split-arr, $item);
		// remove item and separator from string
		$string: str-slice($string, $index + 1);
		// find new index of separator
		$index: str-index($string, $separator);
	}
	// add the remaining string to list (the last item)
	$split-arr: append($split-arr, $string);

	@return $split-arr;
}

/**
 * utility mixin for declaring multiple properties for multiple breakpoints
 * @param  {list} $values	list of values for breakpoints (in $breakpoint)
 *
 * e.g.
 *
 * @include breakpoint-stepper((
 *         xs: #ff0000,
 *         md: #00ff00,
 *         lg: #0000ff
 *     ), color);
 * 
 */
@mixin breakpoint-stepper($values, $property) {
	@each $k, $v in $values {
		@if map-has-key($breakpoints, $k) {
			@include at($k) {
				#{$property}: $v;
			}
		}
	}
}

/**
 *  Map multiple grid values to a property, modifier is optional
 *	e.g. map-grid-values('padding-left': ('outer-margin', 0.5));
 */
@mixin map-grid-values($maps) {
	//get the first value and start with it
	$first-grid-size: nth($grid-sizes, 1);
	@each $porperty, $gridval in $maps {
		$key: nth($gridval, 1);
		$modifier: 1;
		@if length($gridval) >= 2 {
			$modifier: nth($gridval, 2);
		}

		$grid-value: map-get(nth($first-grid-size, 2), $key);
		#{$porperty}: ($grid-value * $modifier);
	}

	//remove the first value from the map
	$grid-sizes-tail: map-remove($grid-sizes, nth($first-grid-size, 1));

	//create mediaqueries for the rest of the grid-sizes
	@each $grid-size in $grid-sizes-tail {
		$name: nth($grid-size, 1);
		$size: map-get($breakpoints, $name);
		$definitions: nth($grid-size, 2);

		@include at($size) {
			@each $porperty, $gridval in $maps {
				$key: nth($gridval, 1);
				$modifier: 1;
				@if length($gridval) >= 2 {
					$modifier: nth($gridval, 2);
				}
				$grid-value: map-get($definitions, $key);
				#{$porperty}: ($grid-value * $modifier);
			}
		}
	}
}

/**
 * 	init
 */

@mixin yeah-grid-utils-init() {
	:root {
		@include grid-vars-to-css-vars();
	}

	.container {
		@include container();
	}

	.container-full {
		@include container-full();
	}

	.grid {
		@include grid();
	}

	.column-gap {
		@include gutter-width-as('column-gap');
	}

	.row-gap {
		@include gutter-width-as('row-gap');
	}

	.grid-full {
		@include grid-full();
	}
}

@include yeah-grid-utils-init;
