Snugug/eq.js

View on GitHub
sass/_eq.scss

Summary

Maintainability
Test Coverage
//////////////////////////////
// Variables
//////////////////////////////
// Selectors that were called for CSS element queries
$EQ-Selectors: ();

//////////////////////////////
// Error Mixin
//////////////////////////////
@mixin EQSTATECHECK($states, $name) {
  $EQ-Error: 'You need to include a state for the `#{$name}` mixin!';
  @if (length($states) == 0) {
    @if feature-exists(at-error) {
      @error $EQ-Error;
    }
    @else {
      @warn $EQ-Error;
    }
  }
  @else {
    @content;
  }
}

//////////////////////////////
// Element Queries!
//
// $states - List of states to apply styling to; @include eq(small, medium, large)
//////////////////////////////
@mixin eq($states...) {
  @include EQSTATECHECK('eq', $states) {
    //////////////////////////////
    // Markup based Element Queries
    //////////////////////////////
    $extend: unique-id();
    @at-root {
      %#{$extend} {
        @content;
      }
    }
    @each $state in $states {
      &[data-eq-state$="#{$state}"] {
        @extend %#{$extend};
      }
    }
  }
}

//////////////////////////////
// Element Query Stack!
//
// Contains one of the query states!
// $states - List of states to apply styling to; @include eq-contains(small, medium, large)
//  * Space separated list will be treated like an `and` media query; all of the states must be active
//  * Comma separated list will be treated like an `or` media query: at least one of the states must be active
//////////////////////////////
@mixin eq-contains($states...) {
  // Space separator API, so going to do stupid magic
  @if length($states) == 1 {
    $states: nth($states, 1);
  }

  @include EQSTATECHECK('eq', $states) {
    //////////////////////////////
    // Markup based Element Queries
    //////////////////////////////
    $extend: unique-id();
    @at-root {
      %#{$extend} {
        @content;
      }
    }
    @if list-separator($states) == 'space' {
      $stateApply: '';

      @each $state in $states {
        $stateApply: $stateApply + '[data-eq-state~="#{$state}"]';
      }

      &#{$stateApply} {
        @extend %#{$extend};
      }
    }
    @else {
      @each $state in $states {
        &[data-eq-state~="#{$state}"] {
          @extend %#{$extend};
        }
      }
    }
  }
}

//////////////////////////////
// Element Query Points
//
// Prints element query points to element's `:before`
//
// $states - Map of `name: size`; @include eq-pts((small: 400, medium: 600, large: 900))
//////////////////////////////
@mixin eq-pts($states) {
  &:before {
    display: none;
    content: '#{str-slice(inspect($states), 2, -2)}';
  }

  @if not index($EQ-Selectors, '#{&}') {
    $EQ-Selectors: append($EQ-Selectors, '#{&}', 'comma') !global;
  }
}

//////////////////////////////
// Element Query Selectors
//
// Prints list of selectors that were called for CSS element queries to HTML's `:before`
//////////////////////////////
@mixin eq-selectors {
  @at-root {
    html:before {
      display: none;
      content: '#{$EQ-Selectors}';
    }
  }
}