/**
 *
 * @ai-apps/angular v2.152.1-next.0 | _breakpoint.scss
 *
 * Copyright 2014, 2023 IBM
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use '../../../../../layout/modules/convert';
@use 'config' as *;

/// Provide a map and index, and get back the relevant key value
/// @access public
/// @param {Map} $map - Map
/// @param {Integer} $index - Key chain
/// @return {String} Desired value
/// @group @carbon/layout
@function -key-by-index($map, $index) {
  $keys: map.keys($map);
  @return nth($keys, $index);
}

/// Get the value of the next breakpoint, or null for the last breakpoint
/// @param {String} $name - The name of the breakpoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name of the breakpoint and the value is the values for the breakpoint
/// @param {List} $breakpoint-names [map-keys($breakpoints)] - A list of names from the `$breakpoints` map
/// @return {String}
/// @access public
/// @group @carbon/layout
@function breakpoint-next(
  $name,
  $breakpoints: $grid-breakpoints,
  $breakpoint-names: map.keys($breakpoints)
) {
  $n: list.index($breakpoint-names, $name);
  @if $n != null and $n < list.length($breakpoint-names) {
    @return list.nth($breakpoint-names, $n + 1);
  }
  @return null;
}

/// Get the value of the previous breakpoint, or null for the first breakpoint
/// @param {String} $name - The name of the breakpoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name of the breakpoint and the value is the values for the breakpoint
/// @param {List} $breakpoint-names [map-keys($breakpoints)] - A list of names from the `$breakpoints` map
/// @return {String}
/// @access public
/// @group @carbon/layout
@function breakpoint-prev(
  $name,
  $breakpoints: $grid-breakpoints,
  $breakpoint-names: map.keys($breakpoints)
) {
  $n: list.index($breakpoint-names, $name);
  @if $n != null and $n > 1 {
    @return list.nth($breakpoint-names, $n - 1);
  }
  @return null;
}

/// Check to see if the given breakpoint name
/// @param {String} $name - The name of the breakpoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name of the breakpoint and the value is the values for the breakpoint
/// @return {Bool}
/// @access public
/// @group @carbon/layout
@function is-smallest-breakpoint($name, $breakpoints: $grid-breakpoints) {
  @return list.index(map.keys($breakpoints), $name) == 1;
}

/// Returns the largest breakpoint name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @return {String}
/// @access public
/// @group @carbon/layout
@function largest-breakpoint-name($breakpoints: $grid-breakpoints) {
  $total-breakpoints: list.length($breakpoints);
  @return -key-by-index($breakpoints, $total-breakpoints);
}

/// Get the infix for a given breakpoint in a list of breakpoints. Useful for generating the size part in a selector, for example: `.prefix--col-sm-2`.
/// @param {String} $name - The name of the breakpoint
/// @return {String}
/// @access public
/// @group @carbon/layout
@function breakpoint-infix($name) {
  @return '-#{$name}';
}

/// Generate a media query from the width of the given breakpoint to infinity
/// @param {String | Number} $name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint-up($name, $breakpoints: $grid-breakpoints) {
  @if meta.type-of($name) == 'number' {
    @media (min-width: $name) {
      @content;
    }
  } @else if map.has-key($breakpoints, $name) {
    $breakpoint: map.get($breakpoints, $name);
    $width: map.get($breakpoint, width);
    @if is-smallest-breakpoint($name, $breakpoints) {
      @content;
    } @else {
      @media (min-width: $width) {
        @content;
      }
    }
  } @else {
    @error 'Unable to find a breakpoint with name `#{$name}`. Expected one of: (#{map.keys($breakpoints)})';
  }
}

/// Generate a media query for the maximum width of the given styles
/// @param {String | Number} $name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint-down($name, $breakpoints: $grid-breakpoints) {
  @if meta.type-of($name) == 'number' {
    @media (max-width: $name) {
      @content;
    }
  } @else if map.has-key($breakpoints, $name) {
    // We borrow this logic from bootstrap for specifying the value of the
    // max-width. The maximum width is calculated by finding the breakpoint and
    // subtracting .02 from its value. This value is used instead of .01 to
    // avoid rounding issues in Safari
    // https://github.com/twbs/bootstrap/blob/c5b1919deaf5393fcca9e9b9d7ce9c338160d99d/scss/mixins/_breakpoints.scss#L34-L46
    $breakpoint: map.get($breakpoints, $name);
    $width: map.get($breakpoint, width) - 0.02;
    @media (max-width: $width) {
      @content;
    }
  } @else {
    @error 'Unable to find a breakpoint with name `#{$name}`. Expected one of: (#{map.keys($breakpoints)})';
  }
}

/// Generate a media query for the range between the lower and upper breakpoints
/// @param {String | Number} $lower
/// @param {String | Number} $upper
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
  $is-number-lower: meta.type-of($lower) == 'number';
  $is-number-upper: meta.type-of($upper) == 'number';
  $min: if($is-number-lower, $lower, map.get($breakpoints, $lower));
  $max: if($is-number-upper, $upper, map.get($breakpoints, $upper));

  @if $min and $max {
    $min-width: if(not $is-number-lower and $min, map.get($min, width), $min);
    $max-width: if(not $is-number-upper and $max, map.get($max, width), $max);
    @media (min-width: $min-width) and (max-width: $max-width) {
      @content;
    }
  } @else if $min != null and $max == null {
    @include breakpoint-up($lower) {
      @content;
    }
  } @else if $min == null and $max != null {
    @include breakpoint-down($upper) {
      @content;
    }
  } @else {
    @error 'Unable to find a breakpoint to satisfy: (#{$lower},#{$upper}). Expected both to be one of (#{map.keys($breakpoints)}).';
  }
}

/// Generate media query for the largest breakpoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin largest-breakpoint($breakpoints: $grid-breakpoints) {
  @include breakpoint(largest-breakpoint-name()) {
    @content;
  }
}

/// Generate a media query for a given breakpoint
/// @param {String | Number} $name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint($name, $breakpoints: $grid-breakpoints) {
  @include breakpoint-up($name, $breakpoints) {
    @content;
  }
}
