pull/380/head
Glen Cheney 2 years ago
parent 34b086274b
commit 8a4911e100

@ -1,13 +1,3 @@
{ {
"presets": [ "presets": [["@babel/preset-env"]]
[
"@babel/preset-env",
{
"targets": {
"browsers": "> 1%, not dead, not IE < 11, IE 11, not OperaMini all",
"node": "current"
}
}
]
]
} }

@ -0,0 +1,4 @@
> 1%
not dead
not ie <= 11
not OperaMini all

@ -4,7 +4,6 @@ about: Create a report to help us improve
title: '' title: ''
labels: '' labels: ''
assignees: '' assignees: ''
--- ---
**Shuffle version** **Shuffle version**
@ -18,6 +17,7 @@ A minimal JSBin, JSFiddle, Codepen, or a GitHub repository that can reproduce th
**To Reproduce** **To Reproduce**
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
3. Scroll down to '....' 3. Scroll down to '....'
@ -30,15 +30,17 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):** **Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari] - OS: [e.g. iOS]
- Version [e.g. 22] - Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):** **Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1] - Device: [e.g. iPhone6]
- Browser [e.g. stock browser, safari] - OS: [e.g. iOS8.1]
- Version [e.g. 22] - Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: '' title: ''
labels: enhancement labels: enhancement
assignees: '' assignees: ''
--- ---
**Is your feature request related to a problem? Please describe.** **Is your feature request related to a problem? Please describe.**

@ -1,12 +1,12 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: npm - package-ecosystem: npm
directory: "/" directory: '/'
schedule: schedule:
interval: weekly interval: weekly
time: "13:00" time: '13:00'
open-pull-requests-limit: 10 open-pull-requests-limit: 10
ignore: ignore:
- dependency-name: cssnano - dependency-name: cssnano
versions: versions:
- 5.0.0 - 5.0.0

@ -0,0 +1,14 @@
node_modules
dist
coverage
docs/dist
docs/css
docs/_site
prism.js
prism.css
.jekyll-cache
# Prettier can't handle liquid templates AND changes the JSON attributes to use
# double quotes, breaking the parser.
*.html

@ -12,19 +12,19 @@ Without a reduced test case, your issue may be closed.
## Releasing a new version ## Releasing a new version
* Update `changelog.html`. - Update `changelog.html`.
* Run tests. - Run tests.
* Commit changes. - Commit changes.
* `npm version major|minor|patch`. - `npm version major|minor|patch`.
* `npm publish` - `npm publish`
* `git push && git push --tags` - `git push && git push --tags`
* Create a [new release](https://github.com/Vestride/Shuffle/releases/new) on GitHub. - Create a [new release](https://github.com/Vestride/Shuffle/releases/new) on GitHub.
## Running locally ## Running locally
This project uses [Jekyll](https://jekyllrb.com/). This project uses [Jekyll](https://jekyllrb.com/).
* Head over to [their quickstart guide](https://jekyllrb.com/docs/quickstart/) to setup jekyll. - Head over to [their quickstart guide](https://jekyllrb.com/docs/quickstart/) to setup jekyll.
* Install npm dependencies `npm install`. - Install npm dependencies `npm install`.
* Run `npm run watch` to rebuild, start the jekyll server, and watch for changes. - Run `npm run watch` to rebuild, start the jekyll server, and watch for changes.
* go to `http://localhost:4000` to see it. - go to `http://localhost:4000` to see it.

2328
dist/shuffle.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,10 +1,10 @@
source: . source: .
destination: _site destination: _site
plugins_dir: _plugins plugins_dir: _plugins
layouts_dir: _layouts layouts_dir: _layouts
data_dir: _data data_dir: _data
include: ["dist"] include: ['dist']
exclude: ["./_scss"] exclude: ['./_scss']
permalink: /:title permalink: /:title

@ -1,7 +1,6 @@
# Options in this file override ones set in _config.yml # Options in this file override ones set in _config.yml
host: 0.0.0.0 host: 0.0.0.0
environment: "development" environment: 'development'
url: http://localhost:4000 url: http://localhost:4000
baseurl: "" baseurl: ''

@ -8,7 +8,7 @@
* Create some DOM elements, append them to the shuffle container, then notify * Create some DOM elements, append them to the shuffle container, then notify
* shuffle about the new items. You could also insert the HTML as a string. * shuffle about the new items. You could also insert the HTML as a string.
*/ */
Demo.prototype.onAppendBoxes = function () { onAppendBoxes() {
var elements = this._getArrayOfElementsToAdd(); var elements = this._getArrayOfElementsToAdd();
elements.forEach(function (element) { elements.forEach(function (element) {

@ -13,12 +13,12 @@ shuffleInstance.filter(function (element) {
<h3>Searching</h3> <h3>Searching</h3>
<div class="code-block"> <div class="code-block">
<pre rel="JavaScript"><code class="language-javascript">// Advanced filtering <pre rel="JavaScript"><code class="language-javascript">// Advanced filtering
Demo.prototype.addSearchFilter = function () { addSearchFilter() {
document.querySelector('.js-shuffle-search').addEventListener('keyup', this._handleSearchKeyup.bind(this)); document.querySelector('.js-shuffle-search').addEventListener('keyup', this._handleSearchKeyup.bind(this));
}; };
// Filter the shuffle instance by items with a title that matches the search input. // Filter the shuffle instance by items with a title that matches the search input.
Demo.prototype._handleSearchKeyup = function (evt) { _handleSearchKeyup(evt) {
var searchText = evt.target.value.toLowerCase(); var searchText = evt.target.value.toLowerCase();
this.shuffle.filter(function (element, shuffle) { this.shuffle.filter(function (element, shuffle) {

@ -4,6 +4,7 @@
GitHub. GitHub.
</p> </p>
<ul> <ul>
<li><code>v6.0.0</code> 2022-02-01 - Drop IE 11, remove misspelled <code>delimeter</code> option, remove <code>matches-selector</code> package.</li>
<li> <li>
<code>v5.4.1</code> 2021-05-29 - Add <code>sortedItems</code> property. Fix <code>getComputedStyle</code> bug for <code>v5.4.1</code> 2021-05-29 - Add <code>sortedItems</code> property. Fix <code>getComputedStyle</code> bug for
Chrome on Windows. Chrome on Windows.

@ -1,7 +1,6 @@
{% if page.requirejs %} {% if page.requirejs %}
<script data-main="{{ site.baseurl }}/js/require-main.js" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.min.js"></script> <script data-main="{{ site.baseurl }}/js/require-main.js" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.min.js"></script>
{% else %} {% else %}
<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=default%2Ces5%2Ces6%2Ces7"></script>
<!-- Syntax highlighting via Prism --> <!-- Syntax highlighting via Prism -->
<script src="{{ site.baseurl }}/js/prism.js"></script> <script src="{{ site.baseurl }}/js/prism.js"></script>
<!-- Shuffle! --> <!-- Shuffle! -->

@ -15,11 +15,11 @@
</div> </div>
<div class="code-block"> <div class="code-block">
<pre rel="JavaScript"><code class="language-javascript">Demo.prototype.addSorting = function () { <pre rel="JavaScript"><code class="language-javascript">addSorting() {
document.querySelector('.sort-options').addEventListener('change', this._handleSortChange.bind(this)); document.querySelector('.sort-options').addEventListener('change', this._handleSortChange.bind(this));
}; };
Demo.prototype._handleSortChange = function (evt) { _handleSortChange(evt) {
var value = evt.target.value; var value = evt.target.value;
function sortByDate(element) { function sortByDate(element) {

@ -10,7 +10,7 @@
</div> </div>
</header> </header>
{% endif %} {% endif %}
<main role="main" id="main"> <main id="main">
{{ content }} {{ content }}
</main> </main>
{% include footer.html %} {% include footer.html %}

@ -150,7 +150,7 @@ photoCredit: false
<h3>Adding elements</h3> <h3>Adding elements</h3>
<p>Wherever you add the element in the DOM is where it will show up in the grid (assuming you&rsquo;re using the default sort-by-dom-order). With this in mind, you can append, prepend, or insert elements wherever you need to get them to show up in the right order.</p> <p>Wherever you add the element in the DOM is where it will show up in the grid (assuming you&rsquo;re using the default sort-by-dom-order). With this in mind, you can append, prepend, or insert elements wherever you need to get them to show up in the right order.</p>
<div class="code-block"> <div class="code-block">
<pre rel="JavaScript"><code class="language-javascript">Demo.prototype.setupEvents = function () { <pre rel="JavaScript"><code class="language-javascript">setupEvents() {
document.querySelector('#append').addEventListener('click', this.onAppendBoxes.bind(this)); document.querySelector('#append').addEventListener('click', this.onAppendBoxes.bind(this));
}; };
@ -158,7 +158,7 @@ photoCredit: false
* Create some DOM elements, append them to the shuffle container, then notify * Create some DOM elements, append them to the shuffle container, then notify
* shuffle about the new items. You could also insert the HTML as a string. * shuffle about the new items. You could also insert the HTML as a string.
*/ */
Demo.prototype.onAppendBoxes = function () { onAppendBoxes() {
var elements = this._getArrayOfElementsToAdd(); var elements = this._getArrayOfElementsToAdd();
elements.forEach(function (element) { elements.forEach(function (element) {

@ -4,7 +4,7 @@ title: Animate In Demo
description: When elements enter the viewport, they transition in from zero opacity and from the bottom. description: When elements enter the viewport, they transition in from zero opacity and from the bottom.
image: /demos/animated.jpg image: /demos/animated.jpg
prism: true prism: true
externalJS: [ "https://unpkg.com/intersection-observer" ] externalJS: []
extraJS: [ "demos/animate-in.js" ] extraJS: [ "demos/animate-in.js" ]
--- ---
<div class="container"> <div class="container">
@ -38,7 +38,7 @@ extraJS: [ "demos/animate-in.js" ]
<div class="col-12@sm"> <div class="col-12@sm">
<h2>About this demo</h2> <h2>About this demo</h2>
<p>This was inspired by <a href="http://tympanus.net/codrops/">codrops</a>&rsquo; demo <a href="http://tympanus.net/codrops/2013/07/02/loading-effects-for-grid-items-with-css-animations/">Loading effects for grid items with css animations</a>.</p> <p>This was inspired by <a href="http://tympanus.net/codrops/">codrops</a>&rsquo; demo <a href="http://tympanus.net/codrops/2013/07/02/loading-effects-for-grid-items-with-css-animations/">Loading effects for grid items with css animations</a>.</p>
<p><code>IntersectionObserver</code> is used to determine when the elements enter the viewport. <a href="https://github.com/WICG/IntersectionObserver/tree/gh-pages/polyfill">A polyfill</a> is included on the page for browsers which don't support it.</p> <p><code>IntersectionObserver</code> is used to determine when the elements enter the viewport.</p>
</div> </div>
<div class="col-12@sm"> <div class="col-12@sm">
<h2>Source code for this demo</h2> <h2>Source code for this demo</h2>

@ -18,7 +18,7 @@
border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0;
} }
label.btn input[type=radio] { label.btn input[type='radio'] {
position: absolute; position: absolute;
clip: rect(0, 0, 0, 0); clip: rect(0, 0, 0, 0);
pointer-events: none; pointer-events: none;
@ -27,14 +27,14 @@
.btn { .btn {
display: inline-block; display: inline-block;
padding: .75em .8em; padding: 0.75em 0.8em;
text-align: center; text-align: center;
border-radius: 3px; border-radius: 3px;
border: 1px solid $gray20; border: 1px solid $gray20;
color: $gray20; color: $gray20;
font-size: 1rem; font-size: 1rem;
background-color: rgba($gray20, 0); background-color: rgba($gray20, 0);
transition: .2s ease-out; transition: 0.2s ease-out;
cursor: pointer; cursor: pointer;
-webkit-appearance: none; -webkit-appearance: none;
@ -53,13 +53,13 @@
&.active, &.active,
&:active { &:active {
box-shadow: inset 0 1px 2px rgba(0,0,0,.3); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3);
color: white; color: white;
background-color: $gray20; background-color: $gray20;
} }
&:focus.active { &:focus.active {
box-shadow: inset 0 1px 2px rgba(0,0,0,.3), 0 0 0 2px rgba($gray20, 0.4); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba($gray20, 0.4);
} }
&:disabled { &:disabled {
@ -99,7 +99,7 @@ $btn-variants: (
} }
&:focus.active { &:focus.active {
box-shadow: inset 0 1px 2px rgba(0,0,0,.3), 0 0 0 2px rgba($color, 0.4); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba($color, 0.4);
} }
&:disabled { &:disabled {
@ -128,10 +128,10 @@ $btn-variants: (
left: 50%; left: 50%;
width: $size; width: $size;
height: $size; height: $size;
margin-left: -$size / 2; margin-left: -$size * 0.5;
margin-top: -$size / 2; margin-top: -$size * 0.5;
opacity: 0; opacity: 0;
transition: .2s; transition: 0.2s;
} }
// Circle // Circle

@ -7,21 +7,20 @@
.demo-list .figure-wrap img { .demo-list .figure-wrap img {
// Promote to its own layer. makes filters look ok on retina with images // Promote to its own layer. makes filters look ok on retina with images
transform: translateZ(0); transform: translateZ(0);
transition: .1s ease; transition: 0.1s ease;
} }
.demo-list:hover .figure-wrap { .demo-list:hover .figure-wrap {
transform: scale3d( 1, 1, 1 ); transform: scale3d(1, 1, 1);
img { img {
filter: grayscale(1); filter: grayscale(1);
} }
} }
.demo-list:hover .figure-wrap:hover { .demo-list:hover .figure-wrap:hover {
z-index: 2; z-index: 2;
transform: scale3d( 1.05, 1.05, 1 ); transform: scale3d(1.05, 1.05, 1);
img { img {
filter: none; filter: none;
@ -38,11 +37,10 @@
.demo-list .figure-wrap figcaption { .demo-list .figure-wrap figcaption {
height: 2em; height: 2em;
margin-top: .5em; margin-top: 0.5em;
margin-bottom: 1em; margin-bottom: 1em;
} }
.demo-link-container::before { .demo-link-container::before {
content: ''; content: '';
display: inline-block; display: inline-block;
@ -59,7 +57,6 @@ span.demo-link-container::before {
} }
@media screen and (max-width: 47.9375em) { @media screen and (max-width: 47.9375em) {
.demo-list + .demo-list { .demo-list + .demo-list {
margin-top: 1em; margin-top: 1em;
} }

@ -1,4 +1,7 @@
.site-nav { .site-nav {
position: sticky;
top: 0;
z-index: 40;
padding: 10px 0; padding: 10px 0;
border-bottom: 1px solid $gray90; border-bottom: 1px solid $gray90;
margin-bottom: 28px; margin-bottom: 28px;
@ -37,7 +40,7 @@
} }
.site-nav__logo rect { .site-nav__logo rect {
transition: 180ms cubic-bezier(0.4, 0.0, 0.2, 1); transition: 180ms cubic-bezier(0.4, 0, 0.2, 1);
} }
.site-nav__link { .site-nav__link {
@ -51,7 +54,7 @@
.site-nav__dropdown { .site-nav__dropdown {
position: absolute; position: absolute;
z-index: 2; z-index: 50;
top: 40px; top: 40px;
right: 0; right: 0;
opacity: 0; opacity: 0;
@ -130,7 +133,7 @@
border-top: 6px solid currentColor; border-top: 6px solid currentColor;
border-left: 5px solid transparent; border-left: 5px solid transparent;
border-right: 5px solid transparent; border-right: 5px solid transparent;
transition: transform 180ms cubic-bezier(0.4, 0.0, 0.2, 1); transition: transform 180ms cubic-bezier(0.4, 0, 0.2, 1);
} }
.site-nav__link--dropdown-active { .site-nav__link--dropdown-active {
@ -302,7 +305,6 @@
} }
.site-nav__dropdown--simple-links { .site-nav__dropdown--simple-links {
&::before { &::before {
right: 24px; right: 24px;
} }

@ -1,3 +1,5 @@
@use 'sass:math';
$grid-gutter-width: 16px; $grid-gutter-width: 16px;
$grid-columns: 12; $grid-columns: 12;
$grid-container: 'container'; $grid-container: 'container';
@ -8,34 +10,23 @@ $grid-ratio-name: 'aspect';
$grid-ratio-inner-name: 'aspect__inner'; $grid-ratio-inner-name: 'aspect__inner';
$grid-container-padding: ( $grid-container-padding: (
xs: 3.5%, xs: 3.5%,
sm: 7% sm: 7%,
); );
$grid-max-width--desktop: 1200px; $grid-max-width--desktop: 1200px;
$grid-ratios: ( $grid-ratios: ((16, 9), (9, 16), (4, 3), (3, 4), (3, 2), (3, 1), (2, 3), (2, 1), (1, 2), (1, 1));
(16, 9),
(9, 16),
(4, 3),
(3, 4),
(3, 2),
(3, 1),
(2, 3),
(2, 1),
(1, 2),
(1, 1)
);
// 7% => 0.07 // 7% => 0.07
$_grid-padding-pct: map-get($grid-container-padding, "sm") / 100%; $_grid-padding-pct: math.div(map-get($grid-container-padding, 'sm'), 100%);
// 0.07 => 0.14 => 0.86 // 0.07 => 0.14 => 0.86
$_grid-padding-value: 1 - $_grid-padding-pct * 2; $_grid-padding-value: 1 - $_grid-padding-pct * 2;
// Size of the window when the grid row has hit max-width. // Size of the window when the grid row has hit max-width.
$_viewport-at-max-grid-width: $grid-max-width--desktop / $_grid-padding-value; $_viewport-at-max-grid-width: math.div($grid-max-width--desktop, $_grid-padding-value);
$viewport-at-max-grid-width: round($_viewport-at-max-grid-width) + 0px; $viewport-at-max-grid-width: round($_viewport-at-max-grid-width) + 0px;
$padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-pct) + 0px; $padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-pct) + 0px;
@function get-column-selector($number, $breakpoint) { @function get-column-selector($number, $breakpoint) {
@return ".#{$grid-prefix}-#{$number}\\@#{$breakpoint}"; @return '.#{$grid-prefix}-#{$number}\\@#{$breakpoint}';
} }
@function get-grid-breakpoint-selectors($breakpoint) { @function get-grid-breakpoint-selectors($breakpoint) {
@ -56,7 +47,6 @@ $padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-
@return $selectors; @return $selectors;
} }
@mixin make-grid-columns() { @mixin make-grid-columns() {
$selectors: get-all-grid-breakpoint-selectors(); $selectors: get-all-grid-breakpoint-selectors();
@ -66,12 +56,11 @@ $padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-
// Prevent columns from collapsing when empty // Prevent columns from collapsing when empty
min-height: 1px; min-height: 1px;
// Inner gutter via padding // Inner gutter via padding
padding-left: ($grid-gutter-width / 2); padding-left: ($grid-gutter-width * 0.5);
padding-right: ($grid-gutter-width / 2); padding-right: ($grid-gutter-width * 0.5);
} }
} }
@mixin float-grid-columns($breakpoint) { @mixin float-grid-columns($breakpoint) {
$selectors: get-grid-breakpoint-selectors($breakpoint); $selectors: get-grid-breakpoint-selectors($breakpoint);
@ -80,21 +69,20 @@ $padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-
} }
} }
@mixin grid-ratios($breakpoint: '') {
@mixin grid-ratios($breakpoint: "") {
// If there is a grid breakpoint class here, prepend a @. // If there is a grid breakpoint class here, prepend a @.
// e.g. "@sm" or "" when there isn't a class. // e.g. "@sm" or "" when there isn't a class.
@if $breakpoint != "" { @if $breakpoint != '' {
$breakpoint: "\\@" + $breakpoint; $breakpoint: '\\@'+ $breakpoint;
} }
// Note @extend isn't used because it cannot be used within @media directives. // Note @extend isn't used because it cannot be used within @media directives.
@each $list in $grid-ratios { @each $list in $grid-ratios {
$top: nth($list, 1); $top: nth($list, 1);
$bottom: nth($list, 2); $bottom: nth($list, 2);
$name: "#{$top}x#{$bottom}"; $name: '#{$top}x#{$bottom}';
.#{$grid-ratio-name}--#{$name}#{$breakpoint} { .#{$grid-ratio-name}--#{$name}#{$breakpoint} {
padding-bottom: percentage($bottom / $top); padding-bottom: percentage(math.div($bottom, $top));
} }
} }
@ -109,34 +97,34 @@ $padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-
} }
@mixin calc-grid-column($index, $columns, $breakpoint, $type) { @mixin calc-grid-column($index, $columns, $breakpoint, $type) {
@if ($type == "width") and ($index > 0) { @if ($type == 'width') and ($index > 0) {
.#{$grid-prefix}-#{$index}\@#{$breakpoint} { .#{$grid-prefix}-#{$index}\@#{$breakpoint} {
width: percentage(($index / $columns)); width: percentage(math.div($index, $columns));
} }
} }
@if ($type == "push") and ($index > 0) { @if ($type == 'push') and ($index > 0) {
.#{$grid-prefix}-push-#{$index}\@#{$breakpoint} { .#{$grid-prefix}-push-#{$index}\@#{$breakpoint} {
left: percentage(($index / $columns)); left: percentage(math.div($index, $columns));
} }
} }
@if ($type == "push") and ($index == 0) { @if ($type == 'push') and ($index == 0) {
.#{$grid-prefix}-push-0\@#{$breakpoint} { .#{$grid-prefix}-push-0\@#{$breakpoint} {
left: auto; left: auto;
} }
} }
@if ($type == "pull") and ($index > 0) { @if ($type == 'pull') and ($index > 0) {
.#{$grid-prefix}-pull-#{$index}\@#{$breakpoint} { .#{$grid-prefix}-pull-#{$index}\@#{$breakpoint} {
right: percentage(($index / $columns)); right: percentage(math.div($index, $columns));
} }
} }
@if ($type == "pull") and ($index == 0) { @if ($type == 'pull') and ($index == 0) {
.#{$grid-prefix}-pull-0\@#{$breakpoint} { .#{$grid-prefix}-pull-0\@#{$breakpoint} {
right: auto; right: auto;
} }
} }
@if ($type == "offset") { @if ($type == 'offset') {
.#{$grid-prefix}-offset-#{$index}\@#{$breakpoint} { .#{$grid-prefix}-offset-#{$index}\@#{$breakpoint} {
margin-left: percentage(($index / $columns)); margin-left: percentage(math.div($index, $columns));
} }
} }
} }
@ -152,8 +140,8 @@ $padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-
@include float-grid-columns($breakpoint); @include float-grid-columns($breakpoint);
@include grid-ratios($breakpoint); @include grid-ratios($breakpoint);
@include loop-grid-columns($columns, $breakpoint, "width"); @include loop-grid-columns($columns, $breakpoint, 'width');
@include loop-grid-columns($columns, $breakpoint, "pull"); @include loop-grid-columns($columns, $breakpoint, 'pull');
@include loop-grid-columns($columns, $breakpoint, "push"); @include loop-grid-columns($columns, $breakpoint, 'push');
@include loop-grid-columns($columns, $breakpoint, "offset"); @include loop-grid-columns($columns, $breakpoint, 'offset');
} }

@ -1,4 +1,3 @@
// @param {string} bp Breakpoint value. One of `xs, sm, md, lg`. // @param {string} bp Breakpoint value. One of `xs, sm, md, lg`.
// @param {boolean} isMaxWidth By default, the media queries are mobile first, // @param {boolean} isMaxWidth By default, the media queries are mobile first,
// so they use `min-width: __px`. By passing `true`, the mixin will subtract // so they use `min-width: __px`. By passing `true`, the mixin will subtract
@ -6,11 +5,13 @@
// @param {boolean} isScreenOnly Whether to hide this media query from print styles. // @param {boolean} isScreenOnly Whether to hide this media query from print styles.
// //
// Note: For print media, we want the default styles and the xs breakpoint to take effect. // Note: For print media, we want the default styles and the xs breakpoint to take effect.
@use 'sass:math';
@mixin breakpoint($bp, $isMaxWidth: false, $isScreenOnly: true) { @mixin breakpoint($bp, $isMaxWidth: false, $isScreenOnly: true) {
$media-query: get-breakpoint-query($bp, $isMaxWidth); $media-query: get-breakpoint-query($bp, $isMaxWidth);
@if $isScreenOnly { @if $isScreenOnly {
$media-query: "screen and #{$media-query}"; $media-query: 'screen and #{$media-query}';
} }
@media #{$media-query} { @media #{$media-query} {
@ -29,7 +30,7 @@
@mixin clearfix() { @mixin clearfix() {
&::before, &::before,
&::after { &::after {
content: " "; content: ' ';
display: table; display: table;
} }
@ -47,7 +48,7 @@
} }
@mixin aspect($width, $height) { @mixin aspect($width, $height) {
padding-bottom: percentage($height / $width); padding-bottom: percentage(math.div($height, $width));
} }
@mixin no-aspect() { @mixin no-aspect() {
@ -65,9 +66,9 @@
} }
@if map-has-key($breakpoints, $bp) { @if map-has-key($breakpoints, $bp) {
@return "(#{$media}: #{$breakpoint})"; @return '(#{$media}: #{$breakpoint})';
} @else { } @else {
@warn "#{$bp} not recognized. Valid breakpoints: #{map-keys($breakpoints)}"; @warn "#{$bp} not recognized. Valid breakpoints: #{map-keys($breakpoints)}";
@return "screen"; @return 'screen';
} }
} }

@ -3,38 +3,38 @@ $breakpoints: (
sm: 768px, sm: 768px,
md: 1024px, md: 1024px,
lg: 1392px, lg: 1392px,
xl: 1680px xl: 1680px,
); );
// Colors from Flat UI // Colors from Flat UI
$turqoise: #1ABC9C; $turqoise: #1abc9c;
$greenSea: #16A085; $greenSea: #16a085;
$emerald: #2ECC71; $emerald: #2ecc71;
$nephritis: #27AE60; $nephritis: #27ae60;
$river: #3498DB; $river: #3498db;
$belizeHole: #2980B9; $belizeHole: #2980b9;
$amethyst: #9B59B6; $amethyst: #9b59b6;
$wisteria: #8E44AD; $wisteria: #8e44ad;
$wet-asphalt: #34495E; $wet-asphalt: #34495e;
$midnightBlue: #2C3E50; $midnightBlue: #2c3e50;
$sunflower: #F1C40F; $sunflower: #f1c40f;
$orange: #F39C12; $orange: #f39c12;
$carrot: #E67E22; $carrot: #e67e22;
$pumpkin: #D35400; $pumpkin: #d35400;
$alizarin: #E74C3C; $alizarin: #e74c3c;
$pomegranate: #C0392B; $pomegranate: #c0392b;
$clouds: #ECF0F1; $clouds: #ecf0f1;
$silver: #BDC3C7; $silver: #bdc3c7;
$concrete: #95A5A6; $concrete: #95a5a6;
$asbestos: #7F8C8D; $asbestos: #7f8c8d;
$black: #000; $black: #000;
$gray10: $midnightBlue; $gray10: $midnightBlue;
$gray20: $wet-asphalt; $gray20: $wet-asphalt;
$gray30: #5D6D77; $gray30: #5d6d77;
$gray50: $asbestos; $gray50: $asbestos;
$gray60: $concrete; $gray60: $concrete;
$gray80: $silver; $gray80: $silver;
$gray90: #E1E5E6; $gray90: #e1e5e6;
$gray95: $clouds; $gray95: $clouds;
$white: #FFF; $white: #fff;

@ -7,11 +7,11 @@
padding: 0.5em; padding: 0.5em;
font-size: 1rem; font-size: 1rem;
color: $gray20; color: $gray20;
transition: .15s; transition: 0.15s;
&::placeholder { &::placeholder {
color: $gray60; color: $gray60;
transition: .15s; transition: 0.15s;
} }
&:hover { &:hover {

@ -1,9 +1,11 @@
@import "../extensions/grid-framework"; @use 'sass:math';
@import '../extensions/grid-framework';
// .container // .container
.#{$grid-container} { .#{$grid-container} {
padding-left: map-get($grid-container-padding, "xs"); padding-left: map-get($grid-container-padding, 'xs');
padding-right: map-get($grid-container-padding, "xs"); padding-right: map-get($grid-container-padding, 'xs');
@include clearfix(); @include clearfix();
} }
@ -14,8 +16,8 @@
@include clearfix(); @include clearfix();
.#{$grid-row} { .#{$grid-row} {
margin-left: $grid-gutter-width / -2; margin-left: math.div($grid-gutter-width, -2);
margin-right: $grid-gutter-width / -2; margin-right: math.div($grid-gutter-width, -2);
} }
&--centered { &--centered {
@ -50,13 +52,12 @@
@include make-grid(xs, 6); @include make-grid(xs, 6);
@include breakpoint(sm) { @include breakpoint(sm) {
@include make-grid(sm); @include make-grid(sm);
// Add more padding to the container class. // Add more padding to the container class.
.#{$grid-container} { .#{$grid-container} {
padding-left: map-get($grid-container-padding, "sm"); padding-left: map-get($grid-container-padding, 'sm');
padding-right: map-get($grid-container-padding, "sm"); padding-right: map-get($grid-container-padding, 'sm');
} }
.#{$grid-row} { .#{$grid-row} {
@ -65,7 +66,6 @@
} }
@include breakpoint(md) { @include breakpoint(md) {
@include make-grid(md); @include make-grid(md);
} }
@ -73,9 +73,9 @@
position: relative; position: relative;
overflow: visible; overflow: visible;
margin-top: 0.5em; margin-top: 0.5em;
margin-right: calc(-3.5vw - #{($grid-gutter-width / 2)}); margin-right: calc(-3.5vw - #{($grid-gutter-width * 0.5)});
margin-bottom: 0.5em; margin-bottom: 0.5em;
margin-left: calc(-3.5vw - #{($grid-gutter-width / 2)}); margin-left: calc(-3.5vw - #{($grid-gutter-width * 0.5)});
pre { pre {
position: relative; position: relative;
@ -83,23 +83,22 @@
min-height: 56px; min-height: 56px;
padding-top: 1em; padding-top: 1em;
padding-bottom: 1em; padding-bottom: 1em;
padding-left: calc(3.5vw + #{($grid-gutter-width / 2)}); padding-left: calc(3.5vw + #{($grid-gutter-width * 0.5)});
padding-right: calc(3.5vw + #{($grid-gutter-width / 2)}); padding-right: calc(3.5vw + #{($grid-gutter-width * 0.5)});
margin: 0; margin: 0;
} }
} }
@include breakpoint(sm) { @include breakpoint(sm) {
.code-block { .code-block {
margin-left: calc(-7vw - #{($grid-gutter-width / 2)}); margin-left: calc(-7vw - #{($grid-gutter-width * 0.5)});
margin-right: calc(-7vw - #{($grid-gutter-width / 2)}); margin-right: calc(-7vw - #{($grid-gutter-width * 0.5)});
pre { pre {
position: relative; position: relative;
z-index: 1; z-index: 1;
padding-left: calc(7vw + #{($grid-gutter-width / 2)}); padding-left: calc(7vw + #{($grid-gutter-width * 0.5)});
padding-right: calc(7vw + #{($grid-gutter-width / 2)}); padding-right: calc(7vw + #{($grid-gutter-width * 0.5)});
} }
} }
} }
@ -120,14 +119,13 @@
// } // }
@media (min-width: $viewport-at-max-grid-width) { @media (min-width: $viewport-at-max-grid-width) {
.code-block { .code-block {
margin-left: calc(((100vw - #{$grid-max-width--desktop}) / -2) - #{$grid-gutter-width / 2}); margin-left: calc(((100vw - #{$grid-max-width--desktop}) / -2) - #{$grid-gutter-width * 0.5});
margin-right: calc(((100vw - #{$grid-max-width--desktop}) / -2) - #{$grid-gutter-width / 2}); margin-right: calc(((100vw - #{$grid-max-width--desktop}) / -2) - #{$grid-gutter-width * 0.5});
pre { pre {
padding-left: calc(((100vw - #{$grid-max-width--desktop}) / 2) + #{$grid-gutter-width / 2}); padding-left: calc(((100vw - #{$grid-max-width--desktop}) / 2) + #{$grid-gutter-width * 0.5});
padding-right: calc(((100vw - #{$grid-max-width--desktop}) / 2) + #{$grid-gutter-width / 2}); padding-right: calc(((100vw - #{$grid-max-width--desktop}) / 2) + #{$grid-gutter-width * 0.5});
} }
} }
} }

@ -1,15 +1,21 @@
.text-center { text-align: center; } .text-center {
text-align: center;
}
.ib { .ib {
display: inline-block; display: inline-block;
} }
@include breakpoint(sm, true) { @include breakpoint(sm, true) {
.hidden\@xs { display: none; } .hidden\@xs {
display: none;
}
} }
@include breakpoint(sm) { @include breakpoint(sm) {
.visible\@xs { display: none; } .visible\@xs {
display: none;
}
} }
// Hide from both screenreaders and browsers. // Hide from both screenreaders and browsers.
@ -32,7 +38,7 @@
.clearfix, .clearfix,
.clearfix::after { .clearfix::after {
content: " "; content: ' ';
display: table; display: table;
clear: both; clear: both;
} }
@ -45,8 +51,12 @@
float: right; float: right;
} }
.full-width { width: 100%; } .full-width {
.full-height { height: 100%; } width: 100%;
}
.full-height {
height: 100%;
}
.hide-text { .hide-text {
font: 0/0 a; font: 0/0 a;

@ -113,20 +113,20 @@ p {
text-decoration: underline; text-decoration: underline;
} }
code:not([class*="language"]) { code:not([class*='language']) {
padding: 0; padding: 0;
padding-top: 0.2em; padding-top: 0.2em;
padding-bottom: 0.2em; padding-bottom: 0.2em;
margin: 0; margin: 0;
font-size: 85%; font-size: 85%;
color: $gray10; color: $gray10;
background-color: rgba(27,31,35,0.05); background-color: rgba(27, 31, 35, 0.05);
border-radius: 3px; border-radius: 3px;
font-family: Menlo, Consolas, "Liberation Mono", Courier, monospace; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace;
} }
code:not([class*="language"])::before, code:not([class*='language'])::before,
code:not([class*="language"])::after { code:not([class*='language'])::after {
content: "\00a0"; content: '\00a0';
letter-spacing: -.2em; letter-spacing: -0.2em;
} }

@ -1,5 +1,4 @@
@import "../extensions/variables"; @import '../extensions/variables';
.compound-filter-options { .compound-filter-options {
margin-top: 20px; margin-top: 20px;
@ -7,7 +6,6 @@
} }
.filter-group--compound { .filter-group--compound {
button { button {
width: 40px; width: 40px;
height: 40px; height: 40px;
@ -73,14 +71,13 @@
transform: rotate(45deg) scale(0.707106781); transform: rotate(45deg) scale(0.707106781);
} }
@mixin equilateralTriangle($size) { @mixin equilateralTriangle($size) {
$sqrt3: 1.73205080757; $sqrt3: 1.73205080757;
$halfSize: $size / 2; $halfSize: $size * 0.5;
$fullSideWidth: round($sqrt3 * $halfSize); $fullSideWidth: round($sqrt3 * $halfSize);
$leftOver: $size - $fullSideWidth; $leftOver: $size - $fullSideWidth;
padding-top: $leftOver / 2; padding-top: $leftOver * 0.5;
height: 0; height: 0;
width: 0; width: 0;
border-width: 0 $halfSize $fullSideWidth $halfSize; border-width: 0 $halfSize $fullSideWidth $halfSize;

@ -9,7 +9,7 @@
float: none; float: none;
margin: 2em 0; margin: 2em 0;
overflow: hidden; overflow: hidden;
transition: .2s ease-out; transition: 0.2s ease-out;
} }
.question--collapsed { .question--collapsed {
@ -18,7 +18,7 @@
border-width: 0; border-width: 0;
} }
.question--collapsed + .question { .question--collapsed + .question {
margin-top: 0; margin-top: 0;
} }

@ -1,4 +1,3 @@
// Filters // Filters
.filter-label { .filter-label {
display: block; display: block;

@ -1,5 +1,5 @@
@import "./extensions/variables"; @import './extensions/variables';
@import "./extensions/mixins"; @import './extensions/mixins';
/*=============================================*\ /*=============================================*\
Some styles to show off masonry layout Some styles to show off masonry layout
@ -67,15 +67,13 @@ img.picture-item__blur {
} }
@include breakpoint(sm) { @include breakpoint(sm) {
.picture-item--overlay { .picture-item--overlay {
.picture-item__details { .picture-item__details {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
background-color: rgba(black, .6); background-color: rgba(black, 0.6);
color: white; color: white;
overflow: hidden; overflow: hidden;
} }
@ -86,9 +84,7 @@ img.picture-item__blur {
} }
@supports (filter: blur(1px)) and (clip-path: inset(0 0 0 0)) { @supports (filter: blur(1px)) and (clip-path: inset(0 0 0 0)) {
.picture-item--overlay { .picture-item--overlay {
.picture-item__blur { .picture-item__blur {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
@ -112,7 +108,6 @@ img.picture-item__blur {
} }
} }
/* /*
Shuffle needs either relative or absolute positioning on the container Shuffle needs either relative or absolute positioning on the container
It will set it for you, but it'll cause another style recalculation and layout. It will set it for you, but it'll cause another style recalculation and layout.
@ -129,7 +124,6 @@ img.picture-item__blur {
visibility: hidden; visibility: hidden;
} }
/* Animate in styles */ /* Animate in styles */
.shuffle--animatein { .shuffle--animatein {
overflow: visible; overflow: visible;
@ -141,7 +135,7 @@ img.picture-item__blur {
} }
.shuffle--animatein .picture-item__inner--transition { .shuffle--animatein .picture-item__inner--transition {
transition: all .6s ease; transition: all 0.6s ease;
} }
.shuffle--animatein .picture-item.in .picture-item__inner { .shuffle--animatein .picture-item.in .picture-item__inner {
@ -149,10 +143,7 @@ img.picture-item__blur {
transform: translate(0, 0); transform: translate(0, 0);
} }
@include breakpoint(sm, true) { @include breakpoint(sm, true) {
.picture-item { .picture-item {
height: auto; height: auto;
margin-top: 20px; margin-top: 20px;
@ -160,12 +151,12 @@ img.picture-item__blur {
.picture-item__details, .picture-item__details,
.picture-item__description { .picture-item__description {
font-size: .875em; font-size: 0.875em;
padding: .625em; padding: 0.625em;
} }
.picture-item__description { .picture-item__description {
padding-right: .875em; padding-right: 0.875em;
padding-bottom: 1.25em; padding-bottom: 1.25em;
} }

@ -1,16 +1,16 @@
@import "./extensions/variables"; @import './extensions/variables';
@import "./extensions/mixins"; @import './extensions/mixins';
@import "./global-rules/global"; @import './global-rules/global';
@import "./global-rules/type"; @import './global-rules/type';
@import "./global-rules/grid"; @import './global-rules/grid';
@import "./global-rules/forms"; @import './global-rules/forms';
@import "./global-rules/helpers"; @import './global-rules/helpers';
@import "./components/buttons"; @import './components/buttons';
@import "./components/demo-list"; @import './components/demo-list';
@import "./components/site-nav"; @import './components/site-nav';
@import "./pages/homepage-filters"; @import './pages/homepage-filters';
@import "./pages/compound-filters"; @import './pages/compound-filters';
@import "./pages/faq"; @import './pages/faq';

@ -1,183 +1,4 @@
/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+jsx+scss&plugins=line-highlight+file-highlight */ /* PrismJS 1.26.0
/** https://prismjs.com/download.html?#themes=prism&languages=markup+css+clike+javascript+jsx+scss&plugins=line-highlight+file-highlight */
* prism.js default theme for JavaScript, CSS and HTML code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
* Based on dabblet (http://dabblet.com) pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)}
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #a67f59;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
pre[data-line] {
position: relative;
padding: 1em 0 1em 3em;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em; /* Same as .prisms padding-top */
background: hsla(24, 20%, 50%,.08);
background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
pointer-events: none;
line-height: inherit;
white-space: pre;
}
.line-highlight:before,
.line-highlight[data-end]:after {
content: attr(data-start);
position: absolute;
top: .4em;
left: .6em;
min-width: 1em;
padding: 0 .5em;
background-color: hsla(24, 20%, 50%,.4);
color: hsl(24, 20%, 95%);
font: bold 65%/1.5 sans-serif;
text-align: center;
vertical-align: .3em;
border-radius: 999px;
text-shadow: none;
box-shadow: 0 1px white;
}
.line-highlight[data-end]:after {
content: attr(data-end);
top: auto;
bottom: .4em;
}

@ -1 +1 @@
.picture-item{height:220px;margin-left:0;margin-top:24px}.picture-item img{display:block;width:100%}@supports ((-o-object-fit:cover) or (object-fit:cover)){.picture-item img{height:100%;max-width:none;-o-object-fit:cover;object-fit:cover}}.picture-item--h2{height:464px}.picture-item__inner{background:#ecf0f1;height:100%;overflow:hidden;position:relative}img.picture-item__blur{display:none}.picture-item__details{align-items:baseline;display:flex;justify-content:space-between;padding:1em;width:100%}.picture-item__description{margin:0;padding:0 2em 1em 1em;width:100%}.picture-item__title{flex-shrink:0;margin-right:4px}.picture-item__tags{flex-shrink:1;margin:0;text-align:right}@media screen and (min-width:768px){.picture-item--overlay .picture-item__details{background-color:rgba(0,0,0,.6);bottom:0;color:#fff;left:0;overflow:hidden;position:absolute;width:100%}.picture-item--overlay .picture-item__description{display:none}@supports (filter:blur(1px)) and ((-webkit-clip-path:inset(0 0 0 0)) or (clip-path:inset(0 0 0 0))){.picture-item--overlay .picture-item__blur{-webkit-clip-path:inset(170px 0 0 0);clip-path:inset(170px 0 0 0);display:block;filter:blur(7px);left:0;position:absolute;top:0;z-index:1}.picture-item--overlay .picture-item__details{background:none}.picture-item--overlay .picture-item__tags,.picture-item--overlay .picture-item__title{position:relative;z-index:2}}}.my-shuffle-container{overflow:hidden;position:relative}.my-sizer-element{opacity:0;position:absolute;visibility:hidden}.shuffle--animatein{overflow:visible}.shuffle--animatein .picture-item__inner{opacity:0;transform:translateY(220px)}.shuffle--animatein .picture-item__inner--transition{transition:all .6s ease}.shuffle--animatein .picture-item.in .picture-item__inner{opacity:1;transform:translate(0)}@media screen and (max-width:767px){.picture-item{height:auto;margin-top:20px}.picture-item__description,.picture-item__details{font-size:.875em;padding:.625em}.picture-item__description{padding-bottom:1.25em;padding-right:.875em}.picture-item--h2{height:auto}} .picture-item{height:220px;margin-left:0;margin-top:24px}.picture-item img{display:block;width:100%}@supports (object-fit:cover){.picture-item img{height:100%;max-width:none;object-fit:cover}}.picture-item--h2{height:464px}.picture-item__inner{background:#ecf0f1;height:100%;overflow:hidden;position:relative}img.picture-item__blur{display:none}.picture-item__details{align-items:baseline;display:flex;justify-content:space-between;padding:1em;width:100%}.picture-item__description{margin:0;padding:0 2em 1em 1em;width:100%}.picture-item__title{flex-shrink:0;margin-right:4px}.picture-item__tags{flex-shrink:1;margin:0;text-align:right}@media screen and (min-width:768px){.picture-item--overlay .picture-item__details{background-color:#0009;bottom:0;color:#fff;left:0;overflow:hidden;position:absolute;width:100%}.picture-item--overlay .picture-item__description{display:none}@supports (filter:blur(1px)) and ((-webkit-clip-path:inset(0 0 0 0)) or (clip-path:inset(0 0 0 0))){.picture-item--overlay .picture-item__blur{-webkit-clip-path:inset(170px 0 0 0);clip-path:inset(170px 0 0 0);display:block;filter:blur(7px);left:0;position:absolute;top:0;z-index:1}.picture-item--overlay .picture-item__details{background:none}.picture-item--overlay .picture-item__tags,.picture-item--overlay .picture-item__title{position:relative;z-index:2}}}.my-shuffle-container{overflow:hidden;position:relative}.my-sizer-element{opacity:0;position:absolute;visibility:hidden}.shuffle--animatein{overflow:visible}.shuffle--animatein .picture-item__inner{opacity:0;transform:translateY(220px)}.shuffle--animatein .picture-item__inner--transition{transition:all .6s ease}.shuffle--animatein .picture-item.in .picture-item__inner{opacity:1;transform:translate(0)}@media screen and (max-width:767px){.picture-item{height:auto;margin-top:20px}.picture-item__description,.picture-item__details{font-size:.875em;padding:.625em}.picture-item__description{padding-bottom:1.25em;padding-right:.875em}.picture-item--h2{height:auto}}

File diff suppressed because one or more lines are too long

2328
docs/dist/shuffle.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -214,7 +214,6 @@ prism: true
<div class="col-12@sm"> <div class="col-12@sm">
<h2>Dependencies<a href="#dependencies"></a></h2> <h2>Dependencies<a href="#dependencies"></a></h2>
<p>Shuffle's <a href="https://github.com/Vestride/Shuffle/blob/master/package.json">dependencies</a> are bundled with the dist file.</p> <p>Shuffle's <a href="https://github.com/Vestride/Shuffle/blob/master/package.json">dependencies</a> are bundled with the dist file.</p>
<p id="polyfills">Shuffle does, however, expect the following ES6/7 features: <code>Set</code>, <code>Array.from</code>, <code>Object.assign</code>, <code>Array.prototype.find</code>, and <code>Array.prototype.includes</code>. In order to support browsers like IE11 and Safari 8, <strong class="type--underline">you must include a polyfill</strong> for these features. You can use a service like <a href="https://polyfill.io">polyfill.io</a> to only load the polyfills that specific browser needs, or a polyfill script like <a href="https://www.npmjs.com/package/@babel/polyfill">@babel/polyfill</a> (which uses <code>core-js</code> internally).</p>
</div> </div>
</div> </div>
</div> </div>
@ -230,27 +229,28 @@ prism: true
<li>Chrome</li> <li>Chrome</li>
<li>Firefox</li> <li>Firefox</li>
<li>Edge</li> <li>Edge</li>
<li>IE 11</li>
<li>Safari</li> <li>Safari</li>
</ul> </ul>
<p>Depending on what browsers you support, you may <a href="#polyfills">need to polyfill features used by Shuffle</a>.</p> <p>If you still need to support IE 11, you can use Shuffle v5.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section id="be-social"> <section id="share">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12@sm"> <div class="col-12@sm">
<h2>Be Social<a href="#be-social"></a></h2> <h2>Share<a href="#share"></a></h2>
<div class="text-center"> <div>
<a href="https://www.buymeacoffee.com/glen.cheney" target="_blank" style="display:inline-block;">
<img loading="lazy" src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 45px !important;width: 160px !important;" />
</a>
<iframe src="https://ghbtns.com/github-btn.html?user=Vestride&repo=Shuffle&type=star&size=large" frameborder="0" scrolling="0" width="76px" height="30px" title="Star this repository on GitHub"></iframe> <iframe src="https://ghbtns.com/github-btn.html?user=Vestride&repo=Shuffle&type=star&size=large" frameborder="0" scrolling="0" width="76px" height="30px" title="Star this repository on GitHub"></iframe>
<a href="https://twitter.com/share" class="twitter-share-button" data-via="Vestride" data-size="large">Tweet</a> <a href="https://twitter.com/share" class="twitter-share-button" data-via="Vestride" data-size="large">Tweet</a>
<div class="g-plusone" data-annotation="none"></div>
</div> </div>
</div> </div>
</div> </div>
@ -268,12 +268,5 @@ prism: true
</section> </section>
<script> <script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs'); !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/platform.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script> </script>

@ -1,151 +1,140 @@
'use strict'; class Sprite {
constructor(context, img, size) {
var Sprite = function (context, img, size) { this.ctx = context;
this.ctx = context; this.img = img;
this.img = img; this.width = size;
this.width = size; this.height = size;
this.height = size; this.frameWidth = size;
this.frameWidth = size; this.frameHeight = size;
this.frameHeight = size;
};
// Assuming horizontal sprite
Sprite.prototype.getFrame = function (frame) {
return {
x: frame * this.frameWidth,
y: 0,
};
};
Sprite.prototype.clearCanvas = function () {
this.ctx.clearRect(0, 0, this.width, this.height);
};
Sprite.prototype.drawFrame = function (frameNumber) {
var frame = this.getFrame(frameNumber);
// Clear out the last frame
this.clearCanvas();
// Draw to the context. This method is really confusing...
this.ctx.drawImage(
this.img,
frame.x,
frame.y,
this.width,
this.height,
0,
0,
this.width,
this.height
);
};
var Favicon = function (src, numFrames, framesPerAnimation, animationDelay) {
// Variables based on params
this.src = src;
this.numFrames = numFrames;
this.framesPerAnimation = framesPerAnimation;
this.animationDelay = animationDelay;
// Elements
this.canvas = document.createElement('canvas');
this.img = document.createElement('img');
this.html = document.documentElement;
// Calculations
this.size = window.devicePixelRatio > 1 ? 32 : 16;
// If it's not a data url, pick apart the filename and add @2x for retina
if (!this.src.match(/data:/) && window.devicePixelRatio > 1) {
var dot = this.src.lastIndexOf('.');
this.src = this.src.substring(0, dot) + '@2x' + this.src.substring(dot);
} }
this.currentFrame = 0; // Assuming horizontal sprite
getFrame(frame) {
return {
x: frame * this.frameWidth,
y: 0,
};
}
clearCanvas() {
this.ctx.clearRect(0, 0, this.width, this.height);
}
drawFrame(frameNumber) {
var frame = this.getFrame(frameNumber);
// Chrome chokes on this. It looks like it can handle 4 frames per second // Clear out the last frame
this.fps = 24; this.clearCanvas();
// No #favicon element, stop // Draw to the context. This method is really confusing...
if (!document.getElementById('favicon')) { this.ctx.drawImage(this.img, frame.x, frame.y, this.width, this.height, 0, 0, this.width, this.height);
return;
} }
}
class Favicon {
constructor(src, numFrames, framesPerAnimation, animationDelay) {
// Variables based on params
this.src = src;
this.numFrames = numFrames;
this.framesPerAnimation = framesPerAnimation;
this.animationDelay = animationDelay;
// Elements
this.canvas = document.createElement('canvas');
this.img = document.createElement('img');
this.html = document.documentElement;
// Calculations
this.size = window.devicePixelRatio > 1 ? 32 : 16;
// If it's not a data url, pick apart the filename and add @2x for retina
if (!this.src.match(/data:/) && window.devicePixelRatio > 1) {
var dot = this.src.lastIndexOf('.');
this.src = this.src.substring(0, dot) + '@2x' + this.src.substring(dot);
}
// Save context this.currentFrame = 0;
this.ctx = this.canvas.getContext('2d');
// Set canvas dimensions based on device DPI // Chrome chokes on this. It looks like it can handle 4 frames per second
this.canvas.height = this.canvas.width = this.size; this.fps = 24;
// Create a new sprite 32x32 size with 32x32 sprites // No #favicon element, stop
this.sprite = new Sprite(this.ctx, this.img, this.size); if (!document.getElementById('favicon')) {
return;
}
// Bind the image load handler // Save context
this.img.onload = this.onSpriteLoaded.bind(this); this.ctx = this.canvas.getContext('2d');
// Trigger image to load // Set canvas dimensions based on device DPI
this.img.src = this.src; this.canvas.height = this.canvas.width = this.size;
};
Favicon.prototype.getData = function () { // Create a new sprite 32x32 size with 32x32 sprites
return this.canvas.toDataURL('image/png'); this.sprite = new Sprite(this.ctx, this.img, this.size);
};
// Clone the current #favicon and replace it with a new element // Bind the image load handler
// which has the updated data URI href this.img.onload = this.onSpriteLoaded.bind(this);
Favicon.prototype.setFavicon = function () {
var data = this.getData();
var originalFavicon = document.getElementById('favicon');
var clone = originalFavicon.cloneNode(true);
clone.setAttribute('href', data); // Trigger image to load
originalFavicon.parentNode.replaceChild(clone, originalFavicon); this.img.src = this.src;
}; }
// Request Animation Frame Loop getData() {
Favicon.prototype.loop = function (timestamp) { return this.canvas.toDataURL('image/png');
// If not enough time has elapse since the last call
// immediately call the next rAF
if (timestamp - this.lastExecuted < this.timeToElapse) {
return requestAnimationFrame(this.loop.bind(this));
} }
// Increment current frame // Clone the current #favicon and replace it with a new element
this.currentFrame += 1; // which has the updated data URI href
if (this.currentFrame === this.numFrames) { setFavicon() {
this.currentFrame = 0; var data = this.getData();
var originalFavicon = document.getElementById('favicon');
var clone = originalFavicon.cloneNode(true);
clone.setAttribute('href', data);
originalFavicon.parentNode.replaceChild(clone, originalFavicon);
} }
// Completed an animation state // Request Animation Frame Loop
this.timeToElapse = this.currentFrame % this.framesPerAnimation === 0 ? loop(timestamp) {
this.animationDelay : // If not enough time has elapse since the last call
1000 / this.fps; // immediately call the next rAF
if (timestamp - this.lastExecuted < this.timeToElapse) {
return requestAnimationFrame(this.loop.bind(this));
}
// Draw current frame from sprite // Increment current frame
this.sprite.drawFrame(this.currentFrame); this.currentFrame += 1;
if (this.currentFrame === this.numFrames) {
this.currentFrame = 0;
}
// Swap <link> // Completed an animation state
this.setFavicon(); this.timeToElapse = this.currentFrame % this.framesPerAnimation === 0 ? this.animationDelay : 1000 / this.fps;
// Set a timeout to draw again // Draw current frame from sprite
this.lastExecuted = timestamp; this.sprite.drawFrame(this.currentFrame);
// Continue loop // Swap <link>
return requestAnimationFrame(this.loop.bind(this)); this.setFavicon();
};
// Sprite loaded // Set a timeout to draw again
Favicon.prototype.onSpriteLoaded = function () { this.lastExecuted = timestamp;
// Draw the first frame when the image loads
this.sprite.drawFrame(this.currentFrame);
// Swap <link> // Continue loop
this.setFavicon(); return requestAnimationFrame(this.loop.bind(this));
}
// Start loop // Sprite loaded
requestAnimationFrame(this.loop.bind(this)); onSpriteLoaded() {
}; // Draw the first frame when the image loads
this.sprite.drawFrame(this.currentFrame);
// Swap <link>
this.setFavicon();
// Start loop
requestAnimationFrame(this.loop.bind(this));
}
}
new Favicon(window.site_url + '/img/favicon-sprite.png', 21, 7, 3000 * 1); new Favicon(window.site_url + '/img/favicon-sprite.png', 21, 7, 3000 * 1);

@ -2,263 +2,262 @@
var Shuffle = window.Shuffle; var Shuffle = window.Shuffle;
var Demo = function (element) { class Demo {
this.element = element; constructor(element) {
this.initShuffle(); this.element = element;
this.setupEvents(); this.initShuffle();
}; this.setupEvents();
}
// Column width and gutter width options can be functions
Demo.prototype.initShuffle = function () { // Column width and gutter width options can be functions
this.shuffle = new Shuffle(this.element, { initShuffle() {
itemSelector: '.box', this.shuffle = new Shuffle(this.element, {
speed: 250, itemSelector: '.box',
easing: 'ease', speed: 250,
columnWidth: function (containerWidth) { easing: 'ease',
// .box's have a width of 18% columnWidth: function (containerWidth) {
return 0.18 * containerWidth; // .box's have a width of 18%
}, return 0.18 * containerWidth;
},
gutterWidth: function (containerWidth) {
// .box's have a margin-left of 2.5% gutterWidth: function (containerWidth) {
return 0.025 * containerWidth; // .box's have a margin-left of 2.5%
}, return 0.025 * containerWidth;
}); },
}; });
}
Demo.prototype.setupEvents = function () {
document.querySelector('#append').addEventListener('click', this.onAppendBoxes.bind(this)); setupEvents() {
document.querySelector('#prepend').addEventListener('click', this.onPrependBoxes.bind(this)); document.querySelector('#append').addEventListener('click', this.onAppendBoxes.bind(this));
document.querySelector('#randomize').addEventListener('click', this.onRandomize.bind(this)); document.querySelector('#prepend').addEventListener('click', this.onPrependBoxes.bind(this));
document.querySelector('#remove').addEventListener('click', this.onRemoveClick.bind(this)); document.querySelector('#randomize').addEventListener('click', this.onRandomize.bind(this));
document.querySelector('#sorter').addEventListener('change', this.onSortChange.bind(this)); document.querySelector('#remove').addEventListener('click', this.onRemoveClick.bind(this));
document.querySelector('#filterer').addEventListener('change', this.onFilterChange.bind(this)); document.querySelector('#sorter').addEventListener('change', this.onSortChange.bind(this));
this.shuffle.element.addEventListener('click', this.onContainerClick.bind(this)); document.querySelector('#filterer').addEventListener('change', this.onFilterChange.bind(this));
this.shuffle.element.addEventListener('click', this.onContainerClick.bind(this));
// Show off some shuffle events
this.shuffle.on(Shuffle.EventType.REMOVED, function (data) { // Show off some shuffle events
console.log(data); this.shuffle.on(Shuffle.EventType.REMOVED, function (data) {
}); console.log(data);
}; });
}
/**
* Generate random DOM elements. /**
* @param {number} itemsToCreate Number of items to create. * Generate random DOM elements.
* @return {Array.<Element>} Array of elements. * @param {number} itemsToCreate Number of items to create.
*/ * @return {Array.<Element>} Array of elements.
Demo.prototype._generateBoxes = function (itemsToCreate) { */
// Creating random elements. You could use an ajax request or clone elements instead. _generateBoxes(itemsToCreate) {
var items = []; // Creating random elements. You could use an ajax request or clone elements instead.
var modifierClasses = ['w2', 'h2', 'w3']; var items = [];
var i = 0; var modifierClasses = ['w2', 'h2', 'w3'];
var i = 0;
for (i = 0; i < itemsToCreate; i++) {
var random = Math.random(); for (i = 0; i < itemsToCreate; i++) {
var box = document.createElement('div'); var random = Math.random();
box.className = 'box'; var box = document.createElement('div');
box.style.backgroundColor = this.getRandomColor(); box.className = 'box';
box.setAttribute('data-reviews', this.getRandomInt(1, 150)); box.style.backgroundColor = this.getRandomColor();
box.setAttribute('data-reviews', this.getRandomInt(1, 150));
// Randomly add a class
if (random > 0.8) { // Randomly add a class
var randomClass = Math.floor(Math.random() * 3); if (random > 0.8) {
box.className = box.className + ' ' + modifierClasses[randomClass]; var randomClass = Math.floor(Math.random() * 3);
box.className = box.className + ' ' + modifierClasses[randomClass];
}
items.push(box);
} }
items.push(box); return items;
}
/**
* Return an array of elements which have already been added to the DOM.
* @return {Array.<Element>}
*/
_getArrayOfElementsToAdd() {
return this._generateBoxes(5);
}
/**
* Create an HTML string to insert. This could, for example, come from an XHR request.
* @return {string} A mock HTML string.
*/
_getHtmlMarkupToAdd() {
var fragment = document.createDocumentFragment();
this._generateBoxes(5).forEach(function (item) {
fragment.appendChild(item);
});
var dummy = document.createElement('div');
dummy.appendChild(fragment);
return dummy.innerHTML;
} }
return items; /**
}; * Create some DOM elements, append them to the shuffle container, then notify
* shuffle about the new items. You could also insert the HTML as a string.
/** */
* Return an array of elements which have already been added to the DOM. onAppendBoxes() {
* @return {Array.<Element>} var elements = this._getArrayOfElementsToAdd();
*/
Demo.prototype._getArrayOfElementsToAdd = function () { elements.forEach(function (element) {
return this._generateBoxes(5); this.shuffle.element.appendChild(element);
}; }, this);
/** // Tell shuffle items have been appended.
* Create an HTML string to insert. This could, for example, come from an XHR request. // It expects an array of elements as the parameter.
* @return {string} A mock HTML string. this.shuffle.add(elements);
*/
Demo.prototype._getHtmlMarkupToAdd = function () {
var fragment = document.createDocumentFragment();
this._generateBoxes(5).forEach(function (item) {
fragment.appendChild(item);
});
var dummy = document.createElement('div');
dummy.appendChild(fragment);
return dummy.innerHTML;
};
/**
* Create some DOM elements, append them to the shuffle container, then notify
* shuffle about the new items. You could also insert the HTML as a string.
*/
Demo.prototype.onAppendBoxes = function () {
var elements = this._getArrayOfElementsToAdd();
elements.forEach(function (element) {
this.shuffle.element.appendChild(element);
}, this);
// Tell shuffle items have been appended.
// It expects an array of elements as the parameter.
this.shuffle.add(elements);
};
/**
* Show that you can prepend elements by inserting before other elements. You
* can either insert a string like in this method or prepend real elements like
* the `onAppendBoxes` method.
*/
Demo.prototype.onPrependBoxes = function () {
var markup = this._getHtmlMarkupToAdd();
// Prepend HTML string.
this.element.insertAdjacentHTML('afterbegin', markup);
// Get the first 5 children of the container (we are inserting 5 items).
var items = Array.prototype.slice.call(this.element.children, 0, 5);
// Notify the instance.
this.shuffle.add(items);
};
Demo.prototype.getRandomInt = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
Demo.prototype.getRandomColor = function () {
return '#' + Math.random().toString(16).slice(2, 8);
};
// Randomly choose some elements to remove
Demo.prototype.onRemoveClick = function () {
var total = this.shuffle.visibleItems;
// None left
if (!total) {
return;
} }
var numberToRemove = Math.min(3, total); /**
var indiciesToRemove = []; * Show that you can prepend elements by inserting before other elements. You
* can either insert a string like in this method or prepend real elements like
* the `onAppendBoxes` method.
*/
onPrependBoxes() {
var markup = this._getHtmlMarkupToAdd();
// Prepend HTML string.
this.element.insertAdjacentHTML('afterbegin', markup);
// Get the first 5 children of the container (we are inserting 5 items).
var items = Array.prototype.slice.call(this.element.children, 0, 5);
// Notify the instance.
this.shuffle.add(items);
}
// This has the possibility to choose the same index for more than getRandomInt(min, max) {
// one in the array, meaning sometimes less than 3 will be removed return Math.floor(Math.random() * (max - min + 1)) + min;
for (var i = 0; i < numberToRemove; i++) {
indiciesToRemove.push(this.getRandomInt(0, total - 1));
} }
// Make an array of elements to remove. getRandomColor() {
var collection = indiciesToRemove.map(function (index) { return '#' + Math.random().toString(16).slice(2, 8);
return this.shuffle.items[index].element;
}, this);
// Tell shuffle to remove them
this.shuffle.remove(collection);
};
Demo.prototype.onRandomize = function () {
var label = document.getElementById('sorter').querySelector('label.btn.active');
if (label) {
var radio = label.querySelector('input');
radio.checked = false;
label.classList.remove('active');
} }
this.sortBy('random'); // Randomly choose some elements to remove
}; onRemoveClick() {
var total = this.shuffle.visibleItems;
Demo.prototype.toggleActiveClasses = function (event) { // None left
// Add and remove `active` class from buttons. if (!total) {
var buttons = Array.from(event.currentTarget.children); return;
buttons.forEach(function (button) {
if (button.querySelector('input').value === event.target.value) {
button.classList.add('active');
} else {
button.classList.remove('active');
} }
});
}
Demo.prototype.onSortChange = function (evt) { var numberToRemove = Math.min(3, total);
this.toggleActiveClasses(evt); var indiciesToRemove = [];
this.sortBy(evt.target.value);
};
Demo.prototype.sortBy = function (value) { // This has the possibility to choose the same index for more than
var sortOptions; // one in the array, meaning sometimes less than 3 will be removed
for (var i = 0; i < numberToRemove; i++) {
indiciesToRemove.push(this.getRandomInt(0, total - 1));
}
if (value === 'most-reviews') { // Make an array of elements to remove.
sortOptions = { var collection = indiciesToRemove.map(function (index) {
reverse: true, return this.shuffle.items[index].element;
by: this.getReviews, }, this);
};
} else if (value === 'least-reviews') { // Tell shuffle to remove them
sortOptions = { this.shuffle.remove(collection);
by: this.getReviews, }
};
} else if (value === 'random') { onRandomize() {
sortOptions = { randomize: true }; var label = document.getElementById('sorter').querySelector('label.btn.active');
if (label) {
var radio = label.querySelector('input');
radio.checked = false;
label.classList.remove('active');
}
} else { this.sortBy('random');
sortOptions = {};
} }
// Filter elements toggleActiveClasses(event) {
this.shuffle.sort(sortOptions); // Add and remove `active` class from buttons.
}; var buttons = Array.from(event.currentTarget.children);
buttons.forEach(function (button) {
if (button.querySelector('input').value === event.target.value) {
button.classList.add('active');
} else {
button.classList.remove('active');
}
});
}
Demo.prototype.getReviews = function (element) { onSortChange(evt) {
return parseInt(element.getAttribute('data-reviews'), 10); this.toggleActiveClasses(evt);
} this.sortBy(evt.target.value);
}
sortBy(value) {
var sortOptions;
if (value === 'most-reviews') {
sortOptions = {
reverse: true,
by: this.getReviews,
};
} else if (value === 'least-reviews') {
sortOptions = {
by: this.getReviews,
};
} else if (value === 'random') {
sortOptions = { randomize: true };
} else {
sortOptions = {};
}
Demo.prototype.onFilterChange = function (event) { // Filter elements
this.toggleActiveClasses(event); this.shuffle.sort(sortOptions);
this.filterBy(event.target.value);
};
Demo.prototype.filterBy = function (value) {
var filterBy;
var _this = this;
if (value === 'none') {
filterBy = Shuffle.ALL_ITEMS;
} else if (value === 'odd-reviews') {
filterBy = function (element) {
return _this.getReviews(element) % 2 === 1;
};
} else {
filterBy = function (element) {
return _this.getReviews(element) % 2 === 0;
};
} }
this.shuffle.filter(filterBy); getReviews(element) {
}; return parseInt(element.getAttribute('data-reviews'), 10);
/**
* Remove a shuffle item when it's clicked.
* @param {Object} event Event object.
*/
Demo.prototype.onContainerClick = function (event) {
// Bail in older browsers. https://caniuse.com/#feat=element-closest
if (typeof event.target.closest !== 'function') {
return;
} }
var element = event.target.closest('.box'); onFilterChange(event) {
if (element !== null) { this.toggleActiveClasses(event);
this.shuffle.remove([element]); this.filterBy(event.target.value);
} }
};
filterBy(value) {
var filterBy;
var _this = this;
if (value === 'none') {
filterBy = Shuffle.ALL_ITEMS;
} else if (value === 'odd-reviews') {
filterBy = function (element) {
return _this.getReviews(element) % 2 === 1;
};
} else {
filterBy = function (element) {
return _this.getReviews(element) % 2 === 0;
};
}
this.shuffle.filter(filterBy);
}
/**
* Remove a shuffle item when it's clicked.
* @param {Object} event Event object.
*/
onContainerClick(event) {
// Bail in older browsers. https://caniuse.com/#feat=element-closest
if (typeof event.target.closest !== 'function') {
return;
}
var element = event.target.closest('.box');
if (element !== null) {
this.shuffle.remove([element]);
}
}
}
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
window.demo = new Demo(document.getElementById('my-shuffle')); window.demo = new Demo(document.getElementById('my-shuffle'));

@ -6,8 +6,6 @@ var loadMoreButton = document.getElementById('load-more-button');
var shuffleInstance; var shuffleInstance;
// Fetch first page of results from the API. // Fetch first page of results from the API.
// You should probably polyfill `fetch` if you're going to copy this demo.
// https://github.com/github/fetch
fetch('https://reqres.in/api/users?page=' + currentPage) fetch('https://reqres.in/api/users?page=' + currentPage)
.then(function (response) { .then(function (response) {
return response.json(); return response.json();

@ -1,56 +1,56 @@
'use strict';
var Shuffle = window.Shuffle; var Shuffle = window.Shuffle;
var Demo = function () { class Demo {
this.element = document.getElementById('grid'); constructor() {
this.gridItems = this.element.querySelectorAll('.picture-item'); this.element = document.getElementById('grid');
var sizer = this.element.querySelector('.my-sizer-element'); this.gridItems = this.element.querySelectorAll('.picture-item');
var sizer = this.element.querySelector('.my-sizer-element');
this.shuffle = new Shuffle(this.element, {
itemSelector: '.picture-item', this.shuffle = new Shuffle(this.element, {
sizer: sizer, itemSelector: '.picture-item',
}); sizer: sizer,
});
var callback = this.showItemsInViewport.bind(this);
this.observer = new IntersectionObserver(callback, {
threshold: 0.5,
});
// Loop through each grid item and add it to the viewport watcher.
for (var i = 0; i < this.gridItems.length; i++) {
this.observer.observe(this.gridItems[i]);
}
var callback = this.showItemsInViewport.bind(this); // Add the transition class to the items after ones that are in the viewport
this.observer = new window.IntersectionObserver(callback, { // have received the `in` class.
threshold: 0.5, setTimeout(() => {
}); this.addTransitionToItems();
}, 100);
}
// Loop through each grid item and add it to the viewport watcher. /**
for (var i = 0; i < this.gridItems.length; i++) { * Add the `in` class to the element after it comes into view.
this.observer.observe(this.gridItems[i]); */
showItemsInViewport(changes) {
changes.forEach(function (change) {
if (change.isIntersecting) {
change.target.classList.add('in');
}
});
} }
// Add the transition class to the items after ones that are in the viewport /**
// have received the `in` class. * Only the items out of the viewport should transition. This way, the first
setTimeout(function () { * visible ones will snap into place.
this.addTransitionToItems(); */
}.bind(this), 100); addTransitionToItems() {
}; for (var i = 0; i < this.gridItems.length; i++) {
var inner = this.gridItems[i].querySelector('.picture-item__inner');
/** inner.classList.add('picture-item__inner--transition');
* Add the `in` class to the element after it comes into view.
*/
Demo.prototype.showItemsInViewport = function (changes) {
changes.forEach(function (change) {
if (change.isIntersecting) {
change.target.classList.add('in');
} }
});
};
/**
* Only the items out of the viewport should transition. This way, the first
* visible ones will snap into place.
*/
Demo.prototype.addTransitionToItems = function () {
for (var i = 0; i < this.gridItems.length; i++) {
var inner = this.gridItems[i].querySelector('.picture-item__inner');
inner.classList.add('picture-item__inner--transition');
} }
}; }
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', () => {
window.demo = new Demo(); window.demo = new Demo();
}); });

@ -2,139 +2,135 @@
var Shuffle = window.Shuffle; var Shuffle = window.Shuffle;
var Demo = function (element) { class Demo {
this.shapes = Array.from(document.querySelectorAll('.js-shapes input')); constructor(element) {
this.colors = Array.from(document.querySelectorAll('.js-colors button')); this.shapes = Array.from(document.querySelectorAll('.js-shapes input'));
this.colors = Array.from(document.querySelectorAll('.js-colors button'));
this.shuffle = new Shuffle(element, {
easing: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)', // easeOutQuart this.shuffle = new Shuffle(element, {
sizer: '.the-sizer', easing: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)',
}); sizer: '.the-sizer',
this.filters = {
shapes: [],
colors: [],
};
this._bindEventListeners();
};
/**
* Bind event listeners for when the filters change.
*/
Demo.prototype._bindEventListeners = function () {
this._onShapeChange = this._handleShapeChange.bind(this);
this._onColorChange = this._handleColorChange.bind(this);
this.shapes.forEach(function (input) {
input.addEventListener('change', this._onShapeChange);
}, this);
this.colors.forEach(function (button) {
button.addEventListener('click', this._onColorChange);
}, this);
};
/**
* Get the values of each checked input.
* @return {Array.<string>}
*/
Demo.prototype._getCurrentShapeFilters = function () {
return this.shapes.filter(function (input) {
return input.checked;
}).map(function (input) {
return input.value;
});
};
/**
* Get the values of each `active` button.
* @return {Array.<string>}
*/
Demo.prototype._getCurrentColorFilters = function () {
return this.colors.filter(function (button) {
return button.classList.contains('active');
}).map(function (button) {
return button.getAttribute('data-value');
});
};
/**
* A shape input check state changed, update the current filters and filte.r
*/
Demo.prototype._handleShapeChange = function () {
this.filters.shapes = this._getCurrentShapeFilters();
this.filter();
};
/**
* A color button was clicked. Update filters and display.
* @param {Event} evt Click event object.
*/
Demo.prototype._handleColorChange = function (evt) {
var button = evt.currentTarget;
// Treat these buttons like radio buttons where only 1 can be selected.
if (button.classList.contains('active')) {
button.classList.remove('active');
} else {
this.colors.forEach(function (btn) {
btn.classList.remove('active');
}); });
button.classList.add('active'); this.filters = {
shapes: [],
colors: [],
};
this._bindEventListeners();
} }
this.filters.colors = this._getCurrentColorFilters(); /**
this.filter(); * Bind event listeners for when the filters change.
}; */
_bindEventListeners() {
/** this._onShapeChange = this._handleShapeChange.bind(this);
* Filter shuffle based on the current state of filters. this._onColorChange = this._handleColorChange.bind(this);
*/
Demo.prototype.filter = function () { this.shapes.forEach((input) => {
if (this.hasActiveFilters()) { input.addEventListener('change', this._onShapeChange);
this.shuffle.filter(this.itemPassesFilters.bind(this)); }, this);
} else {
this.shuffle.filter(Shuffle.ALL_ITEMS); this.colors.forEach((button) => {
button.addEventListener('click', this._onColorChange);
}, this);
} }
};
/**
/** * Get the values of each checked input.
* If any of the arrays in the `filters` property have a length of more than zero, * @return {Array.<string>}
* that means there is an active filter. */
* @return {boolean} _getCurrentShapeFilters() {
*/ return this.shapes.filter((input) => input.checked).map((input) => input.value);
Demo.prototype.hasActiveFilters = function () {
return Object.keys(this.filters).some(function (key) {
return this.filters[key].length > 0;
}, this);
};
/**
* Determine whether an element passes the current filters.
* @param {Element} element Element to test.
* @return {boolean} Whether it satisfies all current filters.
*/
Demo.prototype.itemPassesFilters = function (element) {
var shapes = this.filters.shapes;
var colors = this.filters.colors;
var shape = element.getAttribute('data-shape');
var color = element.getAttribute('data-color');
// If there are active shape filters and this shape is not in that array.
if (shapes.length > 0 && !shapes.includes(shape)) {
return false;
} }
// If there are active color filters and this color is not in that array. /**
if (colors.length > 0 && !colors.includes(color)) { * Get the values of each `active` button.
return false; * @return {Array.<string>}
*/
_getCurrentColorFilters() {
return this.colors
.filter((button) => button.classList.contains('active'))
.map((button) => button.getAttribute('data-value'));
} }
return true; /**
}; * A shape input check state changed, update the current filters and filte.r
*/
_handleShapeChange() {
this.filters.shapes = this._getCurrentShapeFilters();
this.filter();
}
/**
* A color button was clicked. Update filters and display.
* @param {Event} evt Click event object.
*/
_handleColorChange(evt) {
var button = evt.currentTarget;
// Treat these buttons like radio buttons where only 1 can be selected.
if (button.classList.contains('active')) {
button.classList.remove('active');
} else {
this.colors.forEach((btn) => {
btn.classList.remove('active');
});
button.classList.add('active');
}
this.filters.colors = this._getCurrentColorFilters();
this.filter();
}
/**
* Filter shuffle based on the current state of filters.
*/
filter() {
if (this.hasActiveFilters()) {
this.shuffle.filter(this.itemPassesFilters.bind(this));
} else {
this.shuffle.filter(Shuffle.ALL_ITEMS);
}
}
/**
* If any of the arrays in the `filters` property have a length of more than zero,
* that means there is an active filter.
* @return {boolean}
*/
hasActiveFilters() {
return Object.keys(this.filters).some((key) => {
return this.filters[key].length > 0;
}, this);
}
/**
* Determine whether an element passes the current filters.
* @param {Element} element Element to test.
* @return {boolean} Whether it satisfies all current filters.
*/
itemPassesFilters(element) {
var shapes = this.filters.shapes;
var colors = this.filters.colors;
var shape = element.getAttribute('data-shape');
var color = element.getAttribute('data-color');
// If there are active shape filters and this shape is not in that array.
if (shapes.length > 0 && !shapes.includes(shape)) {
return false;
}
// If there are active color filters and this color is not in that array.
if (colors.length > 0 && !colors.includes(color)) {
return false;
}
return true;
}
}
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', () => {
window.demo = new Demo(document.querySelector('.js-shuffle')); window.demo = new Demo(document.querySelector('.js-shuffle'));
}); });

@ -2,194 +2,194 @@
var Shuffle = window.Shuffle; var Shuffle = window.Shuffle;
var Demo = function (element) { class Demo {
this.element = element; constructor(element) {
this.element = element;
this.shuffle = new Shuffle(element, { this.shuffle = new Shuffle(element, {
itemSelector: '.picture-item', itemSelector: '.picture-item',
sizer: element.querySelector('.my-sizer-element'), sizer: element.querySelector('.my-sizer-element'),
}); });
// Log events. // Log events.
this.addShuffleEventListeners(); this.addShuffleEventListeners();
this._activeFilters = []; this._activeFilters = [];
this.addFilterButtons(); this.addFilterButtons();
this.addSorting(); this.addSorting();
this.addSearchFilter(); this.addSearchFilter();
this.mode = 'exclusive';
};
Demo.prototype.toggleMode = function () {
if (this.mode === 'additive') {
this.mode = 'exclusive'; this.mode = 'exclusive';
} else {
this.mode = 'additive';
} }
};
toggleMode() {
/** if (this.mode === 'additive') {
* Shuffle uses the CustomEvent constructor to dispatch events. You can listen this.mode = 'exclusive';
* for them like you normally would (with jQuery for example). } else {
*/ this.mode = 'additive';
Demo.prototype.addShuffleEventListeners = function () { }
this.shuffle.on(Shuffle.EventType.LAYOUT, function (data) {
console.log('layout. data:', data);
});
this.shuffle.on(Shuffle.EventType.REMOVED, function (data) {
console.log('removed. data:', data);
});
};
Demo.prototype.addFilterButtons = function () {
var options = document.querySelector('.filter-options');
if (!options) {
return;
} }
var filterButtons = Array.from(options.children); /**
* Shuffle uses the CustomEvent constructor to dispatch events. You can listen
* for them like you normally would (with jQuery for example).
*/
addShuffleEventListeners() {
this.shuffle.on(Shuffle.EventType.LAYOUT, (data) => {
console.log('layout. data:', data);
});
this.shuffle.on(Shuffle.EventType.REMOVED, (data) => {
console.log('removed. data:', data);
});
}
filterButtons.forEach(function (button) { addFilterButtons() {
button.addEventListener('click', this._handleFilterClick.bind(this), false); var options = document.querySelector('.filter-options');
}, this);
};
Demo.prototype._handleFilterClick = function (evt) { if (!options) {
var btn = evt.currentTarget; return;
var isActive = btn.classList.contains('active'); }
var btnGroup = btn.getAttribute('data-group');
// You don't need _both_ of these modes. This is only for the demo. var filterButtons = Array.from(options.children);
// For this custom 'additive' mode in the demo, clicking on filter buttons filterButtons.forEach((button) => {
// doesn't remove any other filters. button.addEventListener('click', this._handleFilterClick.bind(this), false);
if (this.mode === 'additive') { }, this);
// If this button is already active, remove it from the list of filters. }
if (isActive) {
this._activeFilters.splice(this._activeFilters.indexOf(btnGroup));
} else {
this._activeFilters.push(btnGroup);
}
btn.classList.toggle('active'); _handleFilterClick(evt) {
var btn = evt.currentTarget;
var isActive = btn.classList.contains('active');
var btnGroup = btn.getAttribute('data-group');
// You don't need _both_ of these modes. This is only for the demo.
// For this custom 'additive' mode in the demo, clicking on filter buttons
// doesn't remove any other filters.
if (this.mode === 'additive') {
// If this button is already active, remove it from the list of filters.
if (isActive) {
this._activeFilters.splice(this._activeFilters.indexOf(btnGroup));
} else {
this._activeFilters.push(btnGroup);
}
// Filter elements btn.classList.toggle('active');
this.shuffle.filter(this._activeFilters);
// 'exclusive' mode lets only one filter button be active at a time. // Filter elements
} else { this.shuffle.filter(this._activeFilters);
this._removeActiveClassFromChildren(btn.parentNode);
var filterGroup; // 'exclusive' mode lets only one filter button be active at a time.
if (isActive) {
btn.classList.remove('active');
filterGroup = Shuffle.ALL_ITEMS;
} else { } else {
btn.classList.add('active'); this._removeActiveClassFromChildren(btn.parentNode);
filterGroup = btnGroup;
} var filterGroup;
if (isActive) {
this.shuffle.filter(filterGroup); btn.classList.remove('active');
} filterGroup = Shuffle.ALL_ITEMS;
}; } else {
btn.classList.add('active');
filterGroup = btnGroup;
}
Demo.prototype._removeActiveClassFromChildren = function (parent) { this.shuffle.filter(filterGroup);
var children = parent.children; }
for (var i = children.length - 1; i >= 0; i--) {
children[i].classList.remove('active');
} }
};
Demo.prototype.addSorting = function () {
var buttonGroup = document.querySelector('.sort-options');
if (!buttonGroup) { _removeActiveClassFromChildren(parent) {
return; var children = parent.children;
for (var i = children.length - 1; i >= 0; i--) {
children[i].classList.remove('active');
}
} }
buttonGroup.addEventListener('change', this._handleSortChange.bind(this)); addSorting() {
}; var buttonGroup = document.querySelector('.sort-options');
Demo.prototype._handleSortChange = function (evt) { if (!buttonGroup) {
// Add and remove `active` class from buttons. return;
var buttons = Array.from(evt.currentTarget.children);
buttons.forEach(function (button) {
if (button.querySelector('input').value === evt.target.value) {
button.classList.add('active');
} else {
button.classList.remove('active');
} }
});
// Create the sort options to give to Shuffle. buttonGroup.addEventListener('change', this._handleSortChange.bind(this));
var value = evt.target.value;
var options = {};
function sortByDate(element) {
return Date.parse(element.getAttribute('data-date-created'));
} }
function sortByTitle(element) { _handleSortChange(evt) {
return element.getAttribute('data-title').toLowerCase(); // Add and remove `active` class from buttons.
} var buttons = Array.from(evt.currentTarget.children);
buttons.forEach((button) => {
if (button.querySelector('input').value === evt.target.value) {
button.classList.add('active');
} else {
button.classList.remove('active');
}
});
if (value === 'date-created') { // Create the sort options to give to Shuffle.
options = { var value = evt.target.value;
reverse: true, var options = {};
by: sortByDate,
};
} else if (value === 'title') {
options = {
by: sortByTitle,
};
}
this.shuffle.sort(options); function sortByDate(element) {
}; return Date.parse(element.getAttribute('data-date-created'));
}
// Advanced filtering function sortByTitle(element) {
Demo.prototype.addSearchFilter = function () { return element.getAttribute('data-title').toLowerCase();
var searchInput = document.querySelector('.js-shuffle-search'); }
if (!searchInput) { if (value === 'date-created') {
return; options = {
} reverse: true,
by: sortByDate,
};
} else if (value === 'title') {
options = {
by: sortByTitle,
};
}
searchInput.addEventListener('input', this._handleSearchKeyup.bind(this)); this.shuffle.sort(options);
}; }
/** // Advanced filtering
* Filter the shuffle instance by items with a title that matches the search input. addSearchFilter() {
* @param {Event} evt Event object. var searchInput = document.querySelector('.js-shuffle-search');
*/
Demo.prototype._handleSearchKeyup = function (evt) {
var searchText = evt.target.value.toLowerCase();
this.shuffle.filter(function (element, shuffle) { if (!searchInput) {
return;
}
// If there is a current filter applied, ignore elements that don't match it. searchInput.addEventListener('input', this._handleSearchKeyup.bind(this));
if (shuffle.group !== Shuffle.ALL_ITEMS) { }
// Get the item's groups.
var groups = JSON.parse(element.getAttribute('data-groups'));
var isElementInCurrentGroup = groups.indexOf(shuffle.group) !== -1;
// Only search elements in the current group /**
if (!isElementInCurrentGroup) { * Filter the shuffle instance by items with a title that matches the search input.
return false; * @param {Event} evt Event object.
*/
_handleSearchKeyup(evt) {
var searchText = evt.target.value.toLowerCase();
this.shuffle.filter((element, shuffle) => {
// If there is a current filter applied, ignore elements that don't match it.
if (shuffle.group !== Shuffle.ALL_ITEMS) {
// Get the item's groups.
var groups = JSON.parse(element.getAttribute('data-groups'));
var isElementInCurrentGroup = groups.indexOf(shuffle.group) !== -1;
// Only search elements in the current group
if (!isElementInCurrentGroup) {
return false;
}
} }
}
var titleElement = element.querySelector('.picture-item__title'); var titleElement = element.querySelector('.picture-item__title');
var titleText = titleElement.textContent.toLowerCase().trim(); var titleText = titleElement.textContent.toLowerCase().trim();
return titleText.indexOf(searchText) !== -1; return titleText.indexOf(searchText) !== -1;
}); });
}; }
}
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', () => {
window.demo = new Demo(document.getElementById('grid')); window.demo = new Demo(document.getElementById('grid'));
}); });

@ -25,7 +25,8 @@ class PhotoGrid extends Component {
// use that here while waiting on a network request. // use that here while waiting on a network request.
const grayPixel = 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=='; const grayPixel = 'data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==';
const blackPixel = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='; const blackPixel = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=';
const greenPixel = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mO02Vz4HwAE9AJhcLBN6AAAAABJRU5ErkJggg=='; const greenPixel =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mO02Vz4HwAE9AJhcLBN6AAAAABJRU5ErkJggg==';
this.state = { this.state = {
photos: [ photos: [
@ -47,12 +48,42 @@ class PhotoGrid extends Component {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(() => { setTimeout(() => {
resolve([ resolve([
{ id: 4, username: '@stickermule', name: 'Sticker Mule', src: 'https://images.unsplash.com/photo-1484244233201-29892afe6a2c?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=14d236624576109b51e85bd5d7ebfbfc' }, {
{ id: 5, username: '@prostoroman', name: 'Roman Logov', src: 'https://images.unsplash.com/photo-1465414829459-d228b58caf6e?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=7a7080fc0699869b1921cb1e7047c5b3' }, id: 4,
{ id: 6, username: '@richienolan', name: 'Richard Nolan', src: 'https://images.unsplash.com/photo-1478033394151-c931d5a4bdd6?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=3c74d594a86e26c5a319f4e17b36146e' }, username: '@stickermule',
{ id: 7, username: '@wexor', name: 'Wexor Tmg', src: 'https://images.unsplash.com/photo-1437622368342-7a3d73a34c8f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=11ff283143c782980861a442a957da8e' }, name: 'Sticker Mule',
{ id: 8, username: '@dnevozhai', name: 'Denys Nevozhai', src: 'https://images.unsplash.com/photo-1465447142348-e9952c393450?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=ea06c0f0700ec469fdcb32e0d4c2928e' }, src: 'https://images.unsplash.com/photo-1484244233201-29892afe6a2c?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=14d236624576109b51e85bd5d7ebfbfc',
{ id: 9, username: '@aronvandepol', name: 'Aron Van de Pol', src: 'https://images.unsplash.com/photo-1469719847081-4757697d117a?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=9a568bc48e42d3bb60c97c0eb3dc20ac' }, },
{
id: 5,
username: '@prostoroman',
name: 'Roman Logov',
src: 'https://images.unsplash.com/photo-1465414829459-d228b58caf6e?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=7a7080fc0699869b1921cb1e7047c5b3',
},
{
id: 6,
username: '@richienolan',
name: 'Richard Nolan',
src: 'https://images.unsplash.com/photo-1478033394151-c931d5a4bdd6?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=3c74d594a86e26c5a319f4e17b36146e',
},
{
id: 7,
username: '@wexor',
name: 'Wexor Tmg',
src: 'https://images.unsplash.com/photo-1437622368342-7a3d73a34c8f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=11ff283143c782980861a442a957da8e',
},
{
id: 8,
username: '@dnevozhai',
name: 'Denys Nevozhai',
src: 'https://images.unsplash.com/photo-1465447142348-e9952c393450?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=ea06c0f0700ec469fdcb32e0d4c2928e',
},
{
id: 9,
username: '@aronvandepol',
name: 'Aron Van de Pol',
src: 'https://images.unsplash.com/photo-1469719847081-4757697d117a?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&h=600&fit=crop&s=9a568bc48e42d3bb60c97c0eb3dc20ac',
},
]); ]);
}, 300); }, 300);
}); });
@ -64,18 +95,23 @@ class PhotoGrid extends Component {
* @return {Promise<Object[]>} Loaded images. * @return {Promise<Object[]>} Loaded images.
*/ */
_whenPhotosLoaded(photos) { _whenPhotosLoaded(photos) {
return Promise.all(photos.map(photo => new Promise((resolve) => { return Promise.all(
const image = document.createElement('img'); photos.map(
image.src = photo.src; (photo) =>
new Promise((resolve) => {
if (image.naturalWidth > 0 || image.complete) { const image = document.createElement('img');
resolve(photo); image.src = photo.src;
} else {
image.onload = () => { if (image.naturalWidth > 0 || image.complete) {
resolve(photo); resolve(photo);
}; } else {
} image.onload = () => {
}))); resolve(photo);
};
}
}),
),
);
} }
componentDidMount() { componentDidMount() {
@ -108,7 +144,9 @@ class PhotoGrid extends Component {
render() { render() {
return ( return (
<div ref={this.element} className="row my-shuffle"> <div ref={this.element} className="row my-shuffle">
{this.state.photos.map(image => <PhotoItem {...image}/>)} {this.state.photos.map((image) => (
<PhotoItem {...image} />
))}
<div ref={this.sizer} className="col-1@xs col-1@sm photo-grid__sizer"></div> <div ref={this.sizer} className="col-1@xs col-1@sm photo-grid__sizer"></div>
</div> </div>
); );
@ -130,7 +168,7 @@ function PhotoItem({ id, username, src, name }) {
</div> </div>
</div> </div>
</div> </div>
) );
} }
/** /**

@ -1,7 +1,5 @@
(function () { class Questions {
'use strict'; constructor() {
var Questions = function () {
this.searchInput = document.querySelector('#search'); this.searchInput = document.querySelector('#search');
this.questions = document.querySelectorAll('.js-question'); this.questions = document.querySelectorAll('.js-question');
@ -15,9 +13,9 @@
window.addEventListener('resize', this.onWindowResize.bind(this)); window.addEventListener('resize', this.onWindowResize.bind(this));
this.setHeights(); this.setHeights();
}; }
Questions.prototype._handleInput = function (evt) { _handleInput(evt) {
var val = evt.target.value.toLowerCase(); var val = evt.target.value.toLowerCase();
// Filter elements based on if their string exists in the product model // Filter elements based on if their string exists in the product model
@ -32,27 +30,26 @@
el.classList.remove('question--collapsed'); el.classList.remove('question--collapsed');
} }
} }
}; }
Questions.prototype.setHeights = function () { setHeights() {
var elements = Array.from(this.questions); var elements = Array.from(this.questions);
elements.forEach(function (element) { elements.forEach((element) => {
element.style.height = ''; element.style.height = '';
}); });
var heights = elements.map(function (element) { var heights = elements.map((element) => {
return element.firstElementChild.offsetHeight; return element.firstElementChild.offsetHeight;
}); });
elements.forEach(function (element, i) { elements.forEach((element, i) => {
element.style.height = heights[i] + 'px'; element.style.height = heights[i] + 'px';
}); });
}; }
onWindowResize() {
Questions.prototype.onWindowResize = function () {
this.setHeights(); this.setHeights();
}; }
}
new Questions(); new Questions();
}());

File diff suppressed because one or more lines are too long

@ -2,14 +2,6 @@ requirejs.config({
baseUrl: window.site_url + '/js', baseUrl: window.site_url + '/js',
paths: { paths: {
shufflejs: '../dist/shuffle', shufflejs: '../dist/shuffle',
polyfill: 'https://polyfill.io/v3/polyfill.min.js?features=default%2Ces5%2Ces6%2Ces7',
},
// Load the polyfill before Shuffle.
shim: {
shufflejs: {
deps: ['polyfill'],
},
}, },
}); });

@ -1,5 +1,5 @@
(function () { class SiteNav {
var SiteNav = function (element) { constructor(element) {
this.element = element; this.element = element;
var buttons = Array.from(document.querySelectorAll('.site-nav__link-toggle')); var buttons = Array.from(document.querySelectorAll('.site-nav__link-toggle'));
var dropdowns = buttons.map(function (button) { var dropdowns = buttons.map(function (button) {
@ -15,9 +15,9 @@
this.handleResize = this.handleResize.bind(this); this.handleResize = this.handleResize.bind(this);
window.addEventListener('resize', this.handleResize); window.addEventListener('resize', this.handleResize);
window.addEventListener('load', this.handleResize); window.addEventListener('load', this.handleResize);
}; }
SiteNav.prototype.toggle = function (event) { toggle(event) {
var button = event.currentTarget; var button = event.currentTarget;
var wrapper = button.parentNode; var wrapper = button.parentNode;
var willOpen = !wrapper.classList.contains('site-nav__link--dropdown-active'); var willOpen = !wrapper.classList.contains('site-nav__link--dropdown-active');
@ -36,16 +36,16 @@
} else { } else {
document.body.classList.toggle('site-nav--open'); document.body.classList.toggle('site-nav--open');
} }
}; }
SiteNav.prototype.handleResize = function () { handleResize() {
var viewportHeight = window.innerHeight; var viewportHeight = window.innerHeight;
var navHeight = this.element.offsetHeight; var navHeight = this.element.offsetHeight;
var dropdowns = Array.from(document.querySelectorAll('.site-nav__dropdown')); var dropdowns = Array.from(document.querySelectorAll('.site-nav__dropdown'));
dropdowns.forEach(function (dropdown) { dropdowns.forEach(function (dropdown) {
dropdown.style.maxHeight = (viewportHeight - navHeight) + 'px'; dropdown.style.maxHeight = viewportHeight - navHeight + 'px';
}); });
}; }
}
new SiteNav(document.querySelector('.site-nav')); new SiteNav(document.querySelector('.site-nav'));
})();

@ -9,6 +9,7 @@ const commonjsOptions = {
const babelOptions = { const babelOptions = {
exclude: 'node_modules/**', exclude: 'node_modules/**',
babelHelpers: 'bundled',
}; };
const minifyOptions = { const minifyOptions = {

@ -2,6 +2,5 @@ const gulp = require('gulp');
// Copy dist directory to docs. GitHub pages don't work with symlinks. // Copy dist directory to docs. GitHub pages don't work with symlinks.
module.exports = function copyDist() { module.exports = function copyDist() {
return gulp.src('dist/*') return gulp.src('dist/*').pipe(gulp.dest('docs/dist/'));
.pipe(gulp.dest('docs/dist/'));
}; };

@ -5,6 +5,5 @@ const shell = require('gulp-shell');
module.exports = function jekyll() { module.exports = function jekyll() {
const cmd = 'jekyll serve --config _config.yml,_config_dev.yml'; const cmd = 'jekyll serve --config _config.yml,_config_dev.yml';
return gulp.src('docs/_config.yml', { read: false }) return gulp.src('docs/_config.yml', { read: false }).pipe(shell([cmd], { cwd: path.join(process.cwd(), 'docs') }));
.pipe(shell([cmd], { cwd: path.join(process.cwd(), 'docs') }));
}; };

@ -2,10 +2,12 @@ const { rollup } = require('rollup');
const { configs } = require('../config'); const { configs } = require('../config');
module.exports = function scripts() { module.exports = function scripts() {
const bundles = configs.map(config => rollup(config).then((bundle) => { const bundles = configs.map((config) =>
config.cache = bundle; rollup(config).then((bundle) => {
return bundle.write(config.output); config.cache = bundle;
})); return bundle.write(config.output);
}),
);
return Promise.all(bundles); return Promise.all(bundles);
}; };

@ -2,8 +2,9 @@ const gulp = require('gulp');
const shell = require('gulp-shell'); const shell = require('gulp-shell');
module.exports = function test() { module.exports = function test() {
return gulp.src('package.json', { return gulp
read: false, .src('package.json', {
}) read: false,
})
.pipe(shell(['npx jest'])); .pipe(shell(['npx jest']));
}; };

@ -7,11 +7,6 @@ gulp.task('css', require('./gulp/tasks/css'));
gulp.task('jekyll', require('./gulp/tasks/jekyll')); gulp.task('jekyll', require('./gulp/tasks/jekyll'));
gulp.task('test', require('./gulp/tasks/test')); gulp.task('test', require('./gulp/tasks/test'));
gulp.task('watch', gulp.series( gulp.task('watch', gulp.series('set-watching', gulp.parallel('css', 'scripts'), 'copy-dist', 'jekyll'));
'set-watching',
gulp.parallel('css', 'scripts'),
'copy-dist',
'jekyll',
));
gulp.task('default', gulp.series('scripts', 'css', 'test', 'copy-dist')); gulp.task('default', gulp.series('scripts', 'css', 'test', 'copy-dist'));

5
index.d.ts vendored

@ -1,4 +1,4 @@
// Type definitions for Shuffle 5.2.2 // Type definitions for Shuffle 6.0.0
// Project: https://github.com/Vestride/Shuffle // Project: https://github.com/Vestride/Shuffle
// Definitions by: Glen Cheney <https://github.com/Vestride> // Definitions by: Glen Cheney <https://github.com/Vestride>
@ -32,9 +32,6 @@ export interface ShuffleOptions {
*/ */
delimiter?: string; delimiter?: string;
/** @deprecated Misspelling that will be removed in v6 */
delimeter?: string;
/** /**
* CSS easing function to use. * CSS easing function to use.
*/ */

@ -1,6 +1,6 @@
{ {
"name": "shufflejs", "name": "shufflejs",
"version": "5.4.1", "version": "6.0.0",
"description": "Categorize, sort, and filter a responsive grid of items", "description": "Categorize, sort, and filter a responsive grid of items",
"keywords": [ "keywords": [
"gallery", "gallery",
@ -47,7 +47,6 @@
], ],
"dependencies": { "dependencies": {
"array-parallel": "^0.1.3", "array-parallel": "^0.1.3",
"matches-selector": "^1.0.0",
"throttleit": "^1.0.0", "throttleit": "^1.0.0",
"tiny-emitter": "^2.1.0" "tiny-emitter": "^2.1.0"
}, },
@ -69,6 +68,7 @@
"gulp-shell": "^0.8.0", "gulp-shell": "^0.8.0",
"jest": "^27.4.7", "jest": "^27.4.7",
"postcss": "^8.4.5", "postcss": "^8.4.5",
"prettier": "^2.5.1",
"rollup": "^2.66.1", "rollup": "^2.66.1",
"rollup-plugin-terser": "^7.0.0", "rollup-plugin-terser": "^7.0.0",
"sass": "^1.49.0", "sass": "^1.49.0",

@ -0,0 +1,7 @@
module.exports = {
printWidth: 120,
trailingComma: 'all',
semi: true,
tabWidth: 2,
singleQuote: true,
};

@ -1,3 +1,3 @@
export default function arrayMax(array) { export default function arrayMax(array) {
return Math.max.apply(Math, array); // eslint-disable-line prefer-spread return Math.max(...array);
} }

2
src/array-min.js vendored

@ -1,3 +1,3 @@
export default function arrayMin(array) { export default function arrayMin(array) {
return Math.min.apply(Math, array); // eslint-disable-line prefer-spread return Math.min(...array);
} }

@ -11,23 +11,22 @@ import testComputedSize from './computed-size';
* will return 'auto' when the element doesn't have margins instead of * will return 'auto' when the element doesn't have margins instead of
* the computed style. * the computed style.
*/ */
export default function getNumberStyle( export default function getNumberStyle(element, style, styles = window.getComputedStyle(element, null)) {
element, style,
styles = window.getComputedStyle(element, null),
) {
let value = getNumber(styles[style]); let value = getNumber(styles[style]);
// Support IE<=11 and W3C spec. // Support IE<=11 and W3C spec.
if (!testComputedSize() && style === 'width') { if (!testComputedSize() && style === 'width') {
value += getNumber(styles.paddingLeft) value +=
+ getNumber(styles.paddingRight) getNumber(styles.paddingLeft) +
+ getNumber(styles.borderLeftWidth) getNumber(styles.paddingRight) +
+ getNumber(styles.borderRightWidth); getNumber(styles.borderLeftWidth) +
getNumber(styles.borderRightWidth);
} else if (!testComputedSize() && style === 'height') { } else if (!testComputedSize() && style === 'height') {
value += getNumber(styles.paddingTop) value +=
+ getNumber(styles.paddingBottom) getNumber(styles.paddingTop) +
+ getNumber(styles.borderTopWidth) getNumber(styles.paddingBottom) +
+ getNumber(styles.borderBottomWidth); getNumber(styles.borderTopWidth) +
getNumber(styles.borderBottomWidth);
} }
return value; return value;

@ -100,9 +100,7 @@ export function getShortColumn(positions, buffer) {
* @param {number} buffer Vertical buffer for the height of items. * @param {number} buffer Vertical buffer for the height of items.
* @return {Point} * @return {Point}
*/ */
export function getItemPosition({ export function getItemPosition({ itemSize, positions, gridSize, total, threshold, buffer }) {
itemSize, positions, gridSize, total, threshold, buffer,
}) {
const span = getColumnSpan(itemSize.width, gridSize, total, threshold); const span = getColumnSpan(itemSize.width, gridSize, total, threshold);
const setY = getAvailablePositions(positions, span, total); const setY = getAvailablePositions(positions, span, total);
const shortColumnIndex = getShortColumn(setY, buffer); const shortColumnIndex = getShortColumn(setY, buffer);
@ -183,13 +181,15 @@ export function getCenteredPositions(itemRects, containerWidth) {
// elements could be in the way). // elements could be in the way).
if (!canMove) { if (!canMove) {
let intersectingRect; let intersectingRect;
const hasOverlap = itemRects.some((itemRect) => rects.some((r) => { const hasOverlap = itemRects.some((itemRect) =>
const intersects = Rect.intersects(itemRect, r); rects.some((r) => {
if (intersects) { const intersects = Rect.intersects(itemRect, r);
intersectingRect = r; if (intersects) {
} intersectingRect = r;
return intersects; }
})); return intersects;
}),
);
// If there is any overlap, replace the overlapping row with the original. // If there is any overlap, replace the overlapping row with the original.
if (hasOverlap) { if (hasOverlap) {
@ -206,7 +206,8 @@ export function getCenteredPositions(itemRects, containerWidth) {
// https://stackoverflow.com/a/10865042/373422 // https://stackoverflow.com/a/10865042/373422
// Then reset sort back to how the items were passed to this method. // Then reset sort back to how the items were passed to this method.
// Remove the wrapper object with index, map to a Point. // Remove the wrapper object with index, map to a Point.
return [].concat.apply([], centeredRows) // eslint-disable-line prefer-spread return centeredRows
.sort((a, b) => (a.id - b.id)) .flat()
.sort((a, b) => a.id - b.id)
.map((itemRect) => new Point(itemRect.left, itemRect.top)); .map((itemRect) => new Point(itemRect.left, itemRect.top));
} }

@ -33,7 +33,7 @@ export default class Rect {
*/ */
static intersects(a, b) { static intersects(a, b) {
return ( return (
a.left < b.left + b.width && b.left < a.left + a.width a.left < b.left + b.width && b.left < a.left + a.width && a.top < b.top + b.height && b.top < a.top + a.height
&& a.top < b.top + b.height && b.top < a.top + a.height); );
} }
} }

@ -69,11 +69,7 @@ class ShuffleItem {
} }
dispose() { dispose() {
this.removeClasses([ this.removeClasses([Classes.HIDDEN, Classes.VISIBLE, Classes.SHUFFLE_ITEM]);
Classes.HIDDEN,
Classes.VISIBLE,
Classes.SHUFFLE_ITEM,
]);
this.element.removeAttribute('style'); this.element.removeAttribute('style');
this.element = null; this.element = null;

@ -1,5 +1,4 @@
import TinyEmitter from 'tiny-emitter'; import TinyEmitter from 'tiny-emitter';
import matches from 'matches-selector';
import throttle from 'throttleit'; import throttle from 'throttleit';
import parallel from 'array-parallel'; import parallel from 'array-parallel';
@ -31,14 +30,7 @@ class Shuffle extends TinyEmitter {
*/ */
constructor(element, options = {}) { constructor(element, options = {}) {
super(); super();
// eslint-disable-next-line prefer-object-spread this.options = { ...Shuffle.options, ...options };
this.options = Object.assign({}, Shuffle.options, options);
// Allow misspelling of delimiter since that's how it used to be.
// Remove in v6.
if (this.options.delimeter) {
this.options.delimiter = this.options.delimeter;
}
this.lastSort = {}; this.lastSort = {};
this.group = Shuffle.ALL_ITEMS; this.group = Shuffle.ALL_ITEMS;
@ -327,7 +319,7 @@ class Shuffle extends TinyEmitter {
_getItems() { _getItems() {
return Array.from(this.element.children) return Array.from(this.element.children)
.filter((el) => matches(el, this.options.itemSelector)) .filter((el) => el.matches(this.options.itemSelector))
.map((el) => new ShuffleItem(el, this.options.isRTL)); .map((el) => new ShuffleItem(el, this.options.isRTL));
} }
@ -641,8 +633,7 @@ class Shuffle extends TinyEmitter {
*/ */
getStylesForTransition(item, styleObject) { getStylesForTransition(item, styleObject) {
// Clone the object to avoid mutating the original. // Clone the object to avoid mutating the original.
// eslint-disable-next-line prefer-object-spread const styles = { ...styleObject };
const styles = Object.assign({}, styleObject);
if (this.options.useTransforms) { if (this.options.useTransforms) {
const sign = this.options.isRTL ? '-' : ''; const sign = this.options.isRTL ? '-' : '';

@ -44,8 +44,7 @@ const defaults = {
* @return {Array<T>} * @return {Array<T>}
*/ */
export default function sorter(arr, options) { export default function sorter(arr, options) {
// eslint-disable-next-line prefer-object-spread const opts = { ...defaults, ...options };
const opts = Object.assign({}, defaults, options);
const original = Array.from(arr); const original = Array.from(arr);
let revert = false; let revert = false;

@ -623,15 +623,6 @@ describe('shuffle', () => {
expect(instance.visibleItems).toBe(3); expect(instance.visibleItems).toBe(3);
}); });
it('can use the old misspelled delimiter option', () => {
instance = new Shuffle(fixture, {
delimeter: ',',
group: 'design',
});
expect(instance.visibleItems).toBe(3);
});
}); });
describe('Custom shuffle item styles', () => { describe('Custom shuffle item styles', () => {

@ -2,7 +2,7 @@
"compilerOptions": { "compilerOptions": {
/* Basic Options */ /* Basic Options */
// "incremental": true, /* Enable incremental compilation */ // "incremental": true, /* Enable incremental compilation */
"target": "ES2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "target": "ES2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
// "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ // "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */ // "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */ // "allowJs": true, /* Allow javascript files to be compiled. */
@ -12,7 +12,7 @@
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */ // "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./build", /* Redirect output structure to the directory. */ "outDir": "./build" /* Redirect output structure to the directory. */,
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */ // "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
@ -23,14 +23,14 @@
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */ /* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */ "strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"strictNullChecks": true, /* Enable strict null checks. */ "strictNullChecks": true /* Enable strict null checks. */,
"strictFunctionTypes": true, /* Enable strict checking of function types. */ "strictFunctionTypes": true /* Enable strict checking of function types. */,
"strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ "strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */,
"strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
/* Additional Checks */ /* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */ // "noUnusedLocals": true, /* Report errors on unused locals. */
@ -39,14 +39,14 @@
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */ /* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */ // "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */ // "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */

Loading…
Cancel
Save