@use "sass:map";
@use "sass:meta";
@use "./variables" as var;

/// A media query mixin that defines a query using max-width. You can pass in a
/// key to the `$breakpoints()` maps to access that value, or pass a value to
/// create your media query. This mixin will shave a pixel off your breakpoint
/// values so that it never overlaps with a min-width usage.
/// @param {string | unit} $point
/// @param {style block} @content - passed in brackets
@mixin media-max($point) {
  @if map.has-key(var.$breakpoints, $point) {
    @media (max-width: (map.get(var.$breakpoints, $point) - 1)) {
      @content;
    }
  }
  @else {
    @if (meta.type-of($point) == number) {
      @media (max-width: ($point - 1)) {
        @content;
      }
    }
  }
}

/// A media query mixin that defines a query using min-width. You can pass in a
/// key to the `$breakpoints()` map to access that value, or pass a value to
/// create your media query.
/// @param {string | unit} $point
/// @param {style block} @content - passed in brackets
@mixin media-min($point) {
  @if map.has-key(var.$breakpoints, $point) {
    @media (min-width: map.get(var.$breakpoints, $point)) {
      @content;
    }
  }
  @else {
    @if (meta.type-of($point) == number) {
      @media (min-width: $point) {
        @content;
      }
    }
  }
}

/// A gap mixin that creates spacing between an elements children comparable to
/// the gap property for flexbox. Optionally pass a direction string for
/// column-gap ("x") and row-gaps ("y") output.
/// @param {number unit} $val - the number unit
/// @param {null | string} $dir - direction to apply flex-gap ("x", "y" or null for x and y)
/// @param {null | true} $imp - whether or not to add `!important` flag
/// @param {string} $prop - the property to apply gap with ("margin" | "padding")
@mixin flex-gap($val, $dir: null, $imp: null, $prop: "margin") {
  @if ($imp) {
    $imp: "!important";
  }
  @else if ($imp == false) {
    $imp: null;
  }

  @if ($dir == "x") {
    margin-left: ($val * -1) #{$imp};

    > * {
      #{$prop}-left: $val #{$imp};
    }
  }
  @else if ($dir == "y") {
    margin-top: ($val * -1) #{$imp};

    > * {
      #{$prop}-top: $val #{$imp};
    }
  }
  @else {
    margin-top: ($val * -1) #{$imp};
    margin-left: ($val * -1) #{$imp};

    > * {
      #{$prop}-top: $val #{$imp};
      #{$prop}-left: $val #{$imp};
    }
  }
}

/// A gap mixin that creates spacing between inline or block level elements.
/// Spacing is added using the `> * + *` selector and can either be applied
/// horizontally or vertically by passing $dir "x" or "y" respectively.
/// @param {number unit} $val - the number unit
/// @param {null | string} $dir - direction to apply gap ("x", "y")
/// @param {null | true} $imp - whether or not to add `!important` flag
@mixin gap($val, $dir: "y", $imp: null) {
  @if ($imp) {
    $imp: "!important";
  }
  @else if ($imp == false) {
    $imp: null;
  }

  @if ($dir == "x") {
    > * + * {
      margin-left: $val #{$imp};
    }
  }
  @else if ($dir == "y") {
    > * + * {
      margin-top: $val #{$imp};
    }
  }
}

/// A utility mixin for quickly setting the width and height of an element.
/// @param {number (with unit) | string} $width - width size unit
/// @param {number (with unit) | string} $height - height size unit
@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}

// Add text overflow styles with ellipsis
@mixin overflow-ellipsis() {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
