{"version":3,"file":"shuffle.min.js","sources":["../../../node_modules/tiny-emitter/index.js","../../../node_modules/array-parallel/index.js","../src/get-number.js","../src/point.js","../src/rect.js","../src/classes.js","../src/shuffle-item.js","../src/computed-size.js","../src/get-number-style.js","../src/sorter.js","../src/on-transition-end.js","../src/array-max.js","../src/layout.js","../src/array-min.js","../src/shuffle.js","../src/hyphenate.js"],"sourcesContent":["function E () {\n  // Keep this empty so it's easier to inherit from\n  // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n  on: function (name, callback, ctx) {\n    var e = this.e || (this.e = {});\n\n    (e[name] || (e[name] = [])).push({\n      fn: callback,\n      ctx: ctx\n    });\n\n    return this;\n  },\n\n  once: function (name, callback, ctx) {\n    var self = this;\n    function listener () {\n      self.off(name, listener);\n      callback.apply(ctx, arguments);\n    };\n\n    listener._ = callback\n    return this.on(name, listener, ctx);\n  },\n\n  emit: function (name) {\n    var data = [].slice.call(arguments, 1);\n    var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n    var i = 0;\n    var len = evtArr.length;\n\n    for (i; i < len; i++) {\n      evtArr[i].fn.apply(evtArr[i].ctx, data);\n    }\n\n    return this;\n  },\n\n  off: function (name, callback) {\n    var e = this.e || (this.e = {});\n    var evts = e[name];\n    var liveEvents = [];\n\n    if (evts && callback) {\n      for (var i = 0, len = evts.length; i < len; i++) {\n        if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n          liveEvents.push(evts[i]);\n      }\n    }\n\n    // Remove event from queue to prevent memory leak\n    // Suggested by https://github.com/lazd\n    // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n    (liveEvents.length)\n      ? e[name] = liveEvents\n      : delete e[name];\n\n    return this;\n  }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n","module.exports = function parallel(fns, context, callback) {\n  if (!callback) {\n    if (typeof context === 'function') {\n      callback = context\n      context = null\n    } else {\n      callback = noop\n    }\n  }\n\n  var pending = fns && fns.length\n  if (!pending) return callback(null, []);\n\n  var finished = false\n  var results = new Array(pending)\n\n  fns.forEach(context ? function (fn, i) {\n    fn.call(context, maybeDone(i))\n  } : function (fn, i) {\n    fn(maybeDone(i))\n  })\n\n  function maybeDone(i) {\n    return function (err, result) {\n      if (finished) return;\n\n      if (err) {\n        callback(err, results)\n        finished = true\n        return\n      }\n\n      results[i] = result\n\n      if (!--pending) callback(null, results);\n    }\n  }\n}\n\nfunction noop() {}\n","/**\n * Always returns a numeric value, given a value. Logic from jQuery's `isNumeric`.\n * @param {*} value Possibly numeric value.\n * @return {number} `value` or zero if `value` isn't numeric.\n */\nexport default function getNumber(value) {\n  return parseFloat(value) || 0;\n}\n","import getNumber from './get-number';\n\nclass Point {\n  /**\n   * Represents a coordinate pair.\n   * @param {number} [x=0] X.\n   * @param {number} [y=0] Y.\n   */\n  constructor(x, y) {\n    this.x = getNumber(x);\n    this.y = getNumber(y);\n  }\n\n  /**\n   * Whether two points are equal.\n   * @param {Point} a Point A.\n   * @param {Point} b Point B.\n   * @return {boolean}\n   */\n  static equals(a, b) {\n    return a.x === b.x && a.y === b.y;\n  }\n}\n\nexport default Point;\n","export default class Rect {\n  /**\n   * Class for representing rectangular regions.\n   * https://github.com/google/closure-library/blob/master/closure/goog/math/rect.js\n   * @param {number} x Left.\n   * @param {number} y Top.\n   * @param {number} w Width.\n   * @param {number} h Height.\n   * @param {number} id Identifier\n   * @constructor\n   */\n  constructor(x, y, w, h, id) {\n    this.id = id;\n\n    /** @type {number} */\n    this.left = x;\n\n    /** @type {number} */\n    this.top = y;\n\n    /** @type {number} */\n    this.width = w;\n\n    /** @type {number} */\n    this.height = h;\n  }\n\n  /**\n   * Returns whether two rectangles intersect.\n   * @param {Rect} a A Rectangle.\n   * @param {Rect} b A Rectangle.\n   * @return {boolean} Whether a and b intersect.\n   */\n  static intersects(a, b) {\n    return (\n      a.left < b.left + b.width && b.left < a.left + a.width && a.top < b.top + b.height && b.top < a.top + a.height\n    );\n  }\n}\n","export default {\n  BASE: 'shuffle',\n  SHUFFLE_ITEM: 'shuffle-item',\n  VISIBLE: 'shuffle-item--visible',\n  HIDDEN: 'shuffle-item--hidden',\n};\n","import Point from './point';\nimport Classes from './classes';\n\nlet id = 0;\n\nclass ShuffleItem {\n  constructor(element, isRTL) {\n    id += 1;\n    this.id = id;\n    this.element = element;\n\n    /**\n     * Set correct direction of item\n     */\n    this.isRTL = isRTL;\n\n    /**\n     * Used to separate items for layout and shrink.\n     */\n    this.isVisible = true;\n\n    /**\n     * Used to determine if a transition will happen. By the time the _layout\n     * and _shrink methods get the ShuffleItem instances, the `isVisible` value\n     * has already been changed by the separation methods, so this property is\n     * needed to know if the item was visible/hidden before the shrink/layout.\n     */\n    this.isHidden = false;\n  }\n\n  show() {\n    this.isVisible = true;\n    this.element.classList.remove(Classes.HIDDEN);\n    this.element.classList.add(Classes.VISIBLE);\n    this.element.removeAttribute('aria-hidden');\n  }\n\n  hide() {\n    this.isVisible = false;\n    this.element.classList.remove(Classes.VISIBLE);\n    this.element.classList.add(Classes.HIDDEN);\n    this.element.setAttribute('aria-hidden', true);\n  }\n\n  init() {\n    this.addClasses([Classes.SHUFFLE_ITEM, Classes.VISIBLE]);\n    this.applyCss(ShuffleItem.Css.INITIAL);\n    this.applyCss(this.isRTL ? ShuffleItem.Css.DIRECTION.rtl : ShuffleItem.Css.DIRECTION.ltr);\n    this.scale = ShuffleItem.Scale.VISIBLE;\n    this.point = new Point();\n  }\n\n  addClasses(classes) {\n    classes.forEach((className) => {\n      this.element.classList.add(className);\n    });\n  }\n\n  removeClasses(classes) {\n    classes.forEach((className) => {\n      this.element.classList.remove(className);\n    });\n  }\n\n  applyCss(obj) {\n    Object.keys(obj).forEach((key) => {\n      this.element.style[key] = obj[key];\n    });\n  }\n\n  dispose() {\n    this.removeClasses([Classes.HIDDEN, Classes.VISIBLE, Classes.SHUFFLE_ITEM]);\n\n    this.element.removeAttribute('style');\n    this.element = null;\n  }\n}\n\nShuffleItem.Css = {\n  INITIAL: {\n    position: 'absolute',\n    top: 0,\n    visibility: 'visible',\n    willChange: 'transform',\n  },\n  DIRECTION: {\n    ltr: {\n      left: 0,\n    },\n    rtl: {\n      right: 0,\n    },\n  },\n  VISIBLE: {\n    before: {\n      opacity: 1,\n      visibility: 'visible',\n    },\n    after: {\n      transitionDelay: '',\n    },\n  },\n  HIDDEN: {\n    before: {\n      opacity: 0,\n    },\n    after: {\n      visibility: 'hidden',\n      transitionDelay: '',\n    },\n  },\n};\n\nShuffleItem.Scale = {\n  VISIBLE: 1,\n  HIDDEN: 0.001,\n};\n\nexport default ShuffleItem;\n","import getNumber from './get-number';\n\nlet value = null;\nexport default () => {\n  if (value !== null) {\n    return value;\n  }\n\n  const element = document.body || document.documentElement;\n  const e = document.createElement('div');\n  e.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';\n  element.appendChild(e);\n\n  const { width } = window.getComputedStyle(e, null);\n  // Fix for issue #314\n  value = Math.round(getNumber(width)) === 10;\n\n  element.removeChild(e);\n\n  return value;\n};\n","import getNumber from './get-number';\nimport testComputedSize from './computed-size';\n\n/**\n * Retrieve the computed style for an element, parsed as a float.\n * @param {Element} element Element to get style for.\n * @param {string} style Style property.\n * @param {CSSStyleDeclaration} [styles] Optionally include clean styles to\n *     use instead of asking for them again.\n * @return {number} The parsed computed value or zero if that fails because IE\n *     will return 'auto' when the element doesn't have margins instead of\n *     the computed style.\n */\nexport default function getNumberStyle(element, style, styles = window.getComputedStyle(element, null)) {\n  let value = getNumber(styles[style]);\n\n  // Support IE<=11 and W3C spec.\n  if (!testComputedSize() && style === 'width') {\n    value +=\n      getNumber(styles.paddingLeft) +\n      getNumber(styles.paddingRight) +\n      getNumber(styles.borderLeftWidth) +\n      getNumber(styles.borderRightWidth);\n  } else if (!testComputedSize() && style === 'height') {\n    value +=\n      getNumber(styles.paddingTop) +\n      getNumber(styles.paddingBottom) +\n      getNumber(styles.borderTopWidth) +\n      getNumber(styles.borderBottomWidth);\n  }\n\n  return value;\n}\n","/**\n * Fisher-Yates shuffle.\n * http://stackoverflow.com/a/962890/373422\n * https://bost.ocks.org/mike/shuffle/\n * @param {Array} array Array to shuffle.\n * @return {Array} Randomly sorted array.\n */\nfunction randomize(array) {\n  let n = array.length;\n\n  while (n) {\n    n -= 1;\n    const i = Math.floor(Math.random() * (n + 1));\n    const temp = array[i];\n    array[i] = array[n];\n    array[n] = temp;\n  }\n\n  return array;\n}\n\nconst defaults = {\n  // Use array.reverse() to reverse the results\n  reverse: false,\n\n  // Sorting function\n  by: null,\n\n  // Custom sort function\n  compare: null,\n\n  // If true, this will skip the sorting and return a randomized order in the array\n  randomize: false,\n\n  // Determines which property of each item in the array is passed to the\n  // sorting method.\n  key: 'element',\n};\n\n/**\n * You can return `undefined` from the `by` function to revert to DOM order.\n * @param {Array<T>} arr Array to sort.\n * @param {SortOptions} options Sorting options.\n * @return {Array<T>}\n */\nexport default function sorter(arr, options) {\n  const opts = { ...defaults, ...options };\n  const original = Array.from(arr);\n  let revert = false;\n\n  if (!arr.length) {\n    return [];\n  }\n\n  if (opts.randomize) {\n    return randomize(arr);\n  }\n\n  // Sort the elements by the opts.by function.\n  // If we don't have opts.by, default to DOM order\n  if (typeof opts.by === 'function') {\n    arr.sort((a, b) => {\n      // Exit early if we already know we want to revert\n      if (revert) {\n        return 0;\n      }\n\n      const valA = opts.by(a[opts.key]);\n      const valB = opts.by(b[opts.key]);\n\n      // If both values are undefined, use the DOM order\n      if (valA === undefined && valB === undefined) {\n        revert = true;\n        return 0;\n      }\n\n      if (valA < valB || valA === 'sortFirst' || valB === 'sortLast') {\n        return -1;\n      }\n\n      if (valA > valB || valA === 'sortLast' || valB === 'sortFirst') {\n        return 1;\n      }\n\n      return 0;\n    });\n  } else if (typeof opts.compare === 'function') {\n    arr.sort(opts.compare);\n  }\n\n  // Revert to the original array if necessary\n  if (revert) {\n    return original;\n  }\n\n  if (opts.reverse) {\n    arr.reverse();\n  }\n\n  return arr;\n}\n","const transitions = {};\nconst eventName = 'transitionend';\nlet count = 0;\n\nfunction uniqueId() {\n  count += 1;\n  return eventName + count;\n}\n\nexport function cancelTransitionEnd(id) {\n  if (transitions[id]) {\n    transitions[id].element.removeEventListener(eventName, transitions[id].listener);\n    transitions[id] = null;\n    return true;\n  }\n\n  return false;\n}\n\nexport function onTransitionEnd(element, callback) {\n  const id = uniqueId();\n  const listener = (evt) => {\n    if (evt.currentTarget === evt.target) {\n      cancelTransitionEnd(id);\n      callback(evt);\n    }\n  };\n\n  element.addEventListener(eventName, listener);\n\n  transitions[id] = { element, listener };\n\n  return id;\n}\n","export default function arrayMax(array) {\n  return Math.max(...array);\n}\n","import Point from './point';\nimport Rect from './rect';\nimport arrayMax from './array-max';\nimport arrayMin from './array-min';\n\n/**\n * Determine the number of columns an items spans.\n * @param {number} itemWidth Width of the item.\n * @param {number} columnWidth Width of the column (includes gutter).\n * @param {number} columns Total number of columns\n * @param {number} threshold A buffer value for the size of the column to fit.\n * @return {number}\n */\nexport function getColumnSpan(itemWidth, columnWidth, columns, threshold) {\n  let columnSpan = itemWidth / columnWidth;\n\n  // If the difference between the rounded column span number and the\n  // calculated column span number is really small, round the number to\n  // make it fit.\n  if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) {\n    // e.g. columnSpan = 4.0089945390298745\n    columnSpan = Math.round(columnSpan);\n  }\n\n  // Ensure the column span is not more than the amount of columns in the whole layout.\n  return Math.min(Math.ceil(columnSpan), columns);\n}\n\n/**\n * Retrieves the column set to use for placement.\n * @param {number} columnSpan The number of columns this current item spans.\n * @param {number} columns The total columns in the grid.\n * @return {Array.<number>} An array of numbers represeting the column set.\n */\nexport function getAvailablePositions(positions, columnSpan, columns) {\n  // The item spans only one column.\n  if (columnSpan === 1) {\n    return positions;\n  }\n\n  // The item spans more than one column, figure out how many different\n  // places it could fit horizontally.\n  // The group count is the number of places within the positions this block\n  // could fit, ignoring the current positions of items.\n  // Imagine a 2 column brick as the second item in a 4 column grid with\n  // 10px height each. Find the places it would fit:\n  // [20, 10, 10, 0]\n  //  |   |   |\n  //  *   *   *\n  //\n  // Then take the places which fit and get the bigger of the two:\n  // max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 10]\n  //\n  // Next, find the first smallest number (the short column).\n  // [20, 10, 10]\n  //      |\n  //      *\n  //\n  // And that's where it should be placed!\n  //\n  // Another example where the second column's item extends past the first:\n  // [10, 20, 10, 0] => [20, 20, 10] => 10\n  const available = [];\n\n  // For how many possible positions for this item there are.\n  for (let i = 0; i <= columns - columnSpan; i++) {\n    // Find the bigger value for each place it could fit.\n    available.push(arrayMax(positions.slice(i, i + columnSpan)));\n  }\n\n  return available;\n}\n\n/**\n * Find index of short column, the first from the left where this item will go.\n *\n * @param {Array.<number>} positions The array to search for the smallest number.\n * @param {number} buffer Optional buffer which is very useful when the height\n *     is a percentage of the width.\n * @return {number} Index of the short column.\n */\nexport function getShortColumn(positions, buffer) {\n  const minPosition = arrayMin(positions);\n  for (let i = 0, len = positions.length; i < len; i++) {\n    if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {\n      return i;\n    }\n  }\n\n  return 0;\n}\n\n/**\n * Determine the location of the next item, based on its size.\n * @param {Object} itemSize Object with width and height.\n * @param {Array.<number>} positions Positions of the other current items.\n * @param {number} gridSize The column width or row height.\n * @param {number} total The total number of columns or rows.\n * @param {number} threshold Buffer value for the column to fit.\n * @param {number} buffer Vertical buffer for the height of items.\n * @return {Point}\n */\nexport function getItemPosition({ itemSize, positions, gridSize, total, threshold, buffer }) {\n  const span = getColumnSpan(itemSize.width, gridSize, total, threshold);\n  const setY = getAvailablePositions(positions, span, total);\n  const shortColumnIndex = getShortColumn(setY, buffer);\n\n  // Position the item\n  const point = new Point(gridSize * shortColumnIndex, setY[shortColumnIndex]);\n\n  // Update the columns array with the new values for each column.\n  // e.g. before the update the columns could be [250, 0, 0, 0] for an item\n  // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].\n  const setHeight = setY[shortColumnIndex] + itemSize.height;\n  for (let i = 0; i < span; i++) {\n    positions[shortColumnIndex + i] = setHeight;\n  }\n\n  return point;\n}\n\n/**\n * This method attempts to center items. This method could potentially be slow\n * with a large number of items because it must place items, then check every\n * previous item to ensure there is no overlap.\n * @param {Array.<Rect>} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Array.<Point>}\n */\nexport function getCenteredPositions(itemRects, containerWidth) {\n  const rowMap = {};\n\n  // Populate rows by their offset because items could jump between rows like:\n  // a   c\n  //  bbb\n  itemRects.forEach((itemRect) => {\n    if (rowMap[itemRect.top]) {\n      // Push the point to the last row array.\n      rowMap[itemRect.top].push(itemRect);\n    } else {\n      // Start of a new row.\n      rowMap[itemRect.top] = [itemRect];\n    }\n  });\n\n  // For each row, find the end of the last item, then calculate\n  // the remaining space by dividing it by 2. Then add that\n  // offset to the x position of each point.\n  let rects = [];\n  const rows = [];\n  const centeredRows = [];\n  Object.keys(rowMap).forEach((key) => {\n    const itemRects = rowMap[key];\n    rows.push(itemRects);\n    const lastItem = itemRects[itemRects.length - 1];\n    const end = lastItem.left + lastItem.width;\n    const offset = Math.round((containerWidth - end) / 2);\n\n    let finalRects = itemRects;\n    let canMove = false;\n    if (offset > 0) {\n      const newRects = [];\n      canMove = itemRects.every((r) => {\n        const newRect = new Rect(r.left + offset, r.top, r.width, r.height, r.id);\n\n        // Check all current rects to make sure none overlap.\n        const noOverlap = !rects.some((r) => Rect.intersects(newRect, r));\n\n        newRects.push(newRect);\n        return noOverlap;\n      });\n\n      // If none of the rectangles overlapped, the whole group can be centered.\n      if (canMove) {\n        finalRects = newRects;\n      }\n    }\n\n    // If the items are not going to be offset, ensure that the original\n    // placement for this row will not overlap previous rows (row-spanning\n    // elements could be in the way).\n    if (!canMove) {\n      let intersectingRect;\n      const hasOverlap = itemRects.some((itemRect) =>\n        rects.some((r) => {\n          const intersects = Rect.intersects(itemRect, r);\n          if (intersects) {\n            intersectingRect = r;\n          }\n          return intersects;\n        }),\n      );\n\n      // If there is any overlap, replace the overlapping row with the original.\n      if (hasOverlap) {\n        const rowIndex = centeredRows.findIndex((items) => items.includes(intersectingRect));\n        centeredRows.splice(rowIndex, 1, rows[rowIndex]);\n      }\n    }\n\n    rects = rects.concat(finalRects);\n    centeredRows.push(finalRects);\n  });\n\n  // Reduce array of arrays to a single array of points.\n  // https://stackoverflow.com/a/10865042/373422\n  // Then reset sort back to how the items were passed to this method.\n  // Remove the wrapper object with index, map to a Point.\n  return centeredRows\n    .flat()\n    .sort((a, b) => a.id - b.id)\n    .map((itemRect) => new Point(itemRect.left, itemRect.top));\n}\n","export default function arrayMin(array) {\n  return Math.min(...array);\n}\n","import TinyEmitter from 'tiny-emitter';\nimport parallel from 'array-parallel';\n\nimport Point from './point';\nimport Rect from './rect';\nimport ShuffleItem from './shuffle-item';\nimport Classes from './classes';\nimport getNumberStyle from './get-number-style';\nimport sorter from './sorter';\nimport { onTransitionEnd, cancelTransitionEnd } from './on-transition-end';\nimport { getItemPosition, getColumnSpan, getAvailablePositions, getShortColumn, getCenteredPositions } from './layout';\nimport arrayMax from './array-max';\nimport hyphenate from './hyphenate';\n\nfunction arrayUnique(x) {\n  return Array.from(new Set(x));\n}\n\n// Used for unique instance variables\nlet id = 0;\n\nclass Shuffle extends TinyEmitter {\n  /**\n   * Categorize, sort, and filter a responsive grid of items.\n   *\n   * @param {Element} element An element which is the parent container for the grid items.\n   * @param {Object} [options=Shuffle.options] Options object.\n   * @constructor\n   */\n  constructor(element, options = {}) {\n    super();\n    this.options = { ...Shuffle.options, ...options };\n\n    this.lastSort = {};\n    this.group = Shuffle.ALL_ITEMS;\n    this.lastFilter = Shuffle.ALL_ITEMS;\n    this.isEnabled = true;\n    this.isDestroyed = false;\n    this.isInitialized = false;\n    this._transitions = [];\n    this.isTransitioning = false;\n    this._queue = [];\n\n    const el = this._getElementOption(element);\n\n    if (!el) {\n      throw new TypeError('Shuffle needs to be initialized with an element.');\n    }\n\n    this.element = el;\n    this.id = `shuffle_${id}`;\n    id += 1;\n\n    this._init();\n    this.isInitialized = true;\n  }\n\n  _init() {\n    this.items = this._getItems();\n    this.sortedItems = this.items;\n\n    this.options.sizer = this._getElementOption(this.options.sizer);\n\n    // Add class and invalidate styles\n    this.element.classList.add(Shuffle.Classes.BASE);\n\n    // Set initial css for each item\n    this._initItems(this.items);\n\n    // If the page has not already emitted the `load` event, call layout on load.\n    // This avoids layout issues caused by images and fonts loading after the\n    // instance has been initialized.\n    if (document.readyState !== 'complete') {\n      const layout = this.layout.bind(this);\n      window.addEventListener('load', function onLoad() {\n        window.removeEventListener('load', onLoad);\n        layout();\n      });\n    }\n\n    // Get container css all in one request. Causes reflow\n    const containerCss = window.getComputedStyle(this.element, null);\n    const containerWidth = Shuffle.getSize(this.element).width;\n\n    // Add styles to the container if it doesn't have them.\n    this._validateStyles(containerCss);\n\n    // We already got the container's width above, no need to cause another\n    // reflow getting it again... Calculate the number of columns there will be\n    this._setColumns(containerWidth);\n\n    // Kick off!\n    this.filter(this.options.group, this.options.initialSort);\n\n    // Bind resize events\n    this._rafId = null;\n    // This is true for all supported browsers, but just to be safe, avoid throwing\n    // an error if ResizeObserver is not present. You can manually add a window resize\n    // event and call `update()` if ResizeObserver is missing, or use Shuffle v5.\n    if ('ResizeObserver' in window) {\n      this._resizeObserver = new ResizeObserver(this._handleResizeCallback.bind(this));\n      this._resizeObserver.observe(this.element);\n    }\n\n    // The shuffle items haven't had transitions set on them yet so the user\n    // doesn't see the first layout. Set them now that the first layout is done.\n    // First, however, a synchronous layout must be caused for the previous\n    // styles to be applied without transitions.\n    this.element.offsetWidth; // eslint-disable-line no-unused-expressions\n    this.setItemTransitions(this.items);\n    this.element.style.transition = `height ${this.options.speed}ms ${this.options.easing}`;\n  }\n\n  /**\n   * Retrieve an element from an option.\n   * @param {string|jQuery|Element} option The option to check.\n   * @return {?Element} The plain element or null.\n   * @private\n   */\n  _getElementOption(option) {\n    // If column width is a string, treat is as a selector and search for the\n    // sizer element within the outermost container\n    if (typeof option === 'string') {\n      return this.element.querySelector(option);\n    }\n\n    // Check for an element\n    if (option && option.nodeType && option.nodeType === 1) {\n      return option;\n    }\n\n    // Check for jQuery object\n    if (option && option.jquery) {\n      return option[0];\n    }\n\n    return null;\n  }\n\n  /**\n   * Ensures the shuffle container has the css styles it needs applied to it.\n   * @param {Object} styles Key value pairs for position and overflow.\n   * @private\n   */\n  _validateStyles(styles) {\n    // Position cannot be static.\n    if (styles.position === 'static') {\n      this.element.style.position = 'relative';\n    }\n\n    // Overflow has to be hidden.\n    if (styles.overflow !== 'hidden') {\n      this.element.style.overflow = 'hidden';\n    }\n  }\n\n  /**\n   * Filter the elements by a category.\n   * @param {string|string[]|function(Element):boolean} [category] Category to\n   *     filter by. If it's given, the last category will be used to filter the items.\n   * @param {Array} [collection] Optionally filter a collection. Defaults to\n   *     all the items.\n   * @return {{visible: ShuffleItem[], hidden: ShuffleItem[]}}\n   * @private\n   */\n  _filter(category = this.lastFilter, collection = this.items) {\n    const set = this._getFilteredSets(category, collection);\n\n    // Individually add/remove hidden/visible classes\n    this._toggleFilterClasses(set);\n\n    // Save the last filter in case elements are appended.\n    this.lastFilter = category;\n\n    // This is saved mainly because providing a filter function (like searching)\n    // will overwrite the `lastFilter` property every time its called.\n    if (typeof category === 'string') {\n      this.group = category;\n    }\n\n    return set;\n  }\n\n  /**\n   * Returns an object containing the visible and hidden elements.\n   * @param {string|string[]|function(Element):boolean} category Category or function to filter by.\n   * @param {ShuffleItem[]} items A collection of items to filter.\n   * @return {{visible: ShuffleItem[], hidden: ShuffleItem[]}}\n   * @private\n   */\n  _getFilteredSets(category, items) {\n    let visible = [];\n    const hidden = [];\n\n    // category === 'all', add visible class to everything\n    if (category === Shuffle.ALL_ITEMS) {\n      visible = items;\n\n      // Loop through each item and use provided function to determine\n      // whether to hide it or not.\n    } else {\n      items.forEach((item) => {\n        if (this._doesPassFilter(category, item.element)) {\n          visible.push(item);\n        } else {\n          hidden.push(item);\n        }\n      });\n    }\n\n    return {\n      visible,\n      hidden,\n    };\n  }\n\n  /**\n   * Test an item to see if it passes a category.\n   * @param {string|string[]|function():boolean} category Category or function to filter by.\n   * @param {Element} element An element to test.\n   * @return {boolean} Whether it passes the category/filter.\n   * @private\n   */\n  _doesPassFilter(category, element) {\n    if (typeof category === 'function') {\n      return category.call(element, element, this);\n    }\n\n    // Check each element's data-groups attribute against the given category.\n    const attr = element.dataset[Shuffle.FILTER_ATTRIBUTE_KEY];\n    const keys = this.options.delimiter ? attr.split(this.options.delimiter) : JSON.parse(attr);\n\n    function testCategory(category) {\n      return keys.includes(category);\n    }\n\n    if (Array.isArray(category)) {\n      if (this.options.filterMode === Shuffle.FilterMode.ANY) {\n        return category.some(testCategory);\n      }\n      return category.every(testCategory);\n    }\n\n    return keys.includes(category);\n  }\n\n  /**\n   * Toggles the visible and hidden class names.\n   * @param {{visible, hidden}} Object with visible and hidden arrays.\n   * @private\n   */\n  _toggleFilterClasses({ visible, hidden }) {\n    visible.forEach((item) => {\n      item.show();\n    });\n\n    hidden.forEach((item) => {\n      item.hide();\n    });\n  }\n\n  /**\n   * Set the initial css for each item\n   * @param {ShuffleItem[]} items Set to initialize.\n   * @private\n   */\n  _initItems(items) {\n    items.forEach((item) => {\n      item.init();\n    });\n  }\n\n  /**\n   * Remove element reference and styles.\n   * @param {ShuffleItem[]} items Set to dispose.\n   * @private\n   */\n  _disposeItems(items) {\n    items.forEach((item) => {\n      item.dispose();\n    });\n  }\n\n  /**\n   * Updates the visible item count.\n   * @private\n   */\n  _updateItemCount() {\n    this.visibleItems = this._getFilteredItems().length;\n  }\n\n  /**\n   * Sets css transform transition on a group of elements. This is not executed\n   * at the same time as `item.init` so that transitions don't occur upon\n   * initialization of a new Shuffle instance.\n   * @param {ShuffleItem[]} items Shuffle items to set transitions on.\n   * @protected\n   */\n  setItemTransitions(items) {\n    const { speed, easing } = this.options;\n    const positionProps = this.options.useTransforms ? ['transform'] : ['top', 'left'];\n\n    // Allow users to transtion other properties if they exist in the `before`\n    // css mapping of the shuffle item.\n    const cssProps = Object.keys(ShuffleItem.Css.HIDDEN.before).map((k) => hyphenate(k));\n    const properties = positionProps.concat(cssProps).join();\n\n    items.forEach((item) => {\n      item.element.style.transitionDuration = `${speed}ms`;\n      item.element.style.transitionTimingFunction = easing;\n      item.element.style.transitionProperty = properties;\n    });\n  }\n\n  _getItems() {\n    return Array.from(this.element.children)\n      .filter((el) => el.matches(this.options.itemSelector))\n      .map((el) => new ShuffleItem(el, this.options.isRTL));\n  }\n\n  /**\n   * Combine the current items array with a new one and sort it by DOM order.\n   * @param {ShuffleItem[]} items Items to track.\n   * @return {ShuffleItem[]}\n   */\n  _mergeNewItems(items) {\n    const children = Array.from(this.element.children);\n    return sorter(this.items.concat(items), {\n      by(element) {\n        return children.indexOf(element);\n      },\n    });\n  }\n\n  _getFilteredItems() {\n    return this.items.filter((item) => item.isVisible);\n  }\n\n  _getConcealedItems() {\n    return this.items.filter((item) => !item.isVisible);\n  }\n\n  /**\n   * Returns the column size, based on column width and sizer options.\n   * @param {number} containerWidth Size of the parent container.\n   * @param {number} gutterSize Size of the gutters.\n   * @return {number}\n   * @private\n   */\n  _getColumnSize(containerWidth, gutterSize) {\n    let size;\n\n    // If the columnWidth property is a function, then the grid is fluid\n    if (typeof this.options.columnWidth === 'function') {\n      size = this.options.columnWidth(containerWidth);\n\n      // columnWidth option isn't a function, are they using a sizing element?\n    } else if (this.options.sizer) {\n      size = Shuffle.getSize(this.options.sizer).width;\n\n      // if not, how about the explicitly set option?\n    } else if (this.options.columnWidth) {\n      size = this.options.columnWidth;\n\n      // or use the size of the first item\n    } else if (this.items.length > 0) {\n      size = Shuffle.getSize(this.items[0].element, true).width;\n\n      // if there's no items, use size of container\n    } else {\n      size = containerWidth;\n    }\n\n    // Don't let them set a column width of zero.\n    if (size === 0) {\n      size = containerWidth;\n    }\n\n    return size + gutterSize;\n  }\n\n  /**\n   * Returns the gutter size, based on gutter width and sizer options.\n   * @param {number} containerWidth Size of the parent container.\n   * @return {number}\n   * @private\n   */\n  _getGutterSize(containerWidth) {\n    let size;\n    if (typeof this.options.gutterWidth === 'function') {\n      size = this.options.gutterWidth(containerWidth);\n    } else if (this.options.sizer) {\n      size = getNumberStyle(this.options.sizer, 'marginLeft');\n    } else {\n      size = this.options.gutterWidth;\n    }\n\n    return size;\n  }\n\n  /**\n   * Calculate the number of columns to be used. Gets css if using sizer element.\n   * @param {number} [containerWidth] Optionally specify a container width if\n   *    it's already available.\n   */\n  _setColumns(containerWidth = Shuffle.getSize(this.element).width) {\n    const gutter = this._getGutterSize(containerWidth);\n    const columnWidth = this._getColumnSize(containerWidth, gutter);\n    let calculatedColumns = (containerWidth + gutter) / columnWidth;\n\n    // Widths given from getStyles are not precise enough...\n    if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) < this.options.columnThreshold) {\n      // e.g. calculatedColumns = 11.998876\n      calculatedColumns = Math.round(calculatedColumns);\n    }\n\n    this.cols = Math.max(Math.floor(calculatedColumns || 0), 1);\n    this.containerWidth = containerWidth;\n    this.colWidth = columnWidth;\n  }\n\n  /**\n   * Adjust the height of the grid\n   */\n  _setContainerSize() {\n    this.element.style.height = `${this._getContainerSize()}px`;\n  }\n\n  /**\n   * Based on the column heights, it returns the biggest one.\n   * @return {number}\n   * @private\n   */\n  _getContainerSize() {\n    return arrayMax(this.positions);\n  }\n\n  /**\n   * Get the clamped stagger amount.\n   * @param {number} index Index of the item to be staggered.\n   * @return {number}\n   */\n  _getStaggerAmount(index) {\n    return Math.min(index * this.options.staggerAmount, this.options.staggerAmountMax);\n  }\n\n  /**\n   * Emit an event from this instance.\n   * @param {string} name Event name.\n   * @param {Object} [data={}] Optional object data.\n   */\n  _dispatch(name, data = {}) {\n    if (this.isDestroyed) {\n      return;\n    }\n\n    data.shuffle = this;\n    this.emit(name, data);\n  }\n\n  /**\n   * Zeros out the y columns array, which is used to determine item placement.\n   * @private\n   */\n  _resetCols() {\n    let i = this.cols;\n    this.positions = [];\n    while (i) {\n      i -= 1;\n      this.positions.push(0);\n    }\n  }\n\n  /**\n   * Loops through each item that should be shown and calculates the x, y position.\n   * @param {ShuffleItem[]} items Array of items that will be shown/layed\n   *     out in order in their array.\n   */\n  _layout(items) {\n    const itemPositions = this._getNextPositions(items);\n\n    let count = 0;\n    items.forEach((item, i) => {\n      function callback() {\n        item.applyCss(ShuffleItem.Css.VISIBLE.after);\n      }\n\n      // If the item will not change its position, do not add it to the render\n      // queue. Transitions don't fire when setting a property to the same value.\n      if (Point.equals(item.point, itemPositions[i]) && !item.isHidden) {\n        item.applyCss(ShuffleItem.Css.VISIBLE.before);\n        callback();\n        return;\n      }\n\n      item.point = itemPositions[i];\n      item.scale = ShuffleItem.Scale.VISIBLE;\n      item.isHidden = false;\n\n      // Clone the object so that the `before` object isn't modified when the\n      // transition delay is added.\n      const styles = this.getStylesForTransition(item, ShuffleItem.Css.VISIBLE.before);\n      styles.transitionDelay = `${this._getStaggerAmount(count)}ms`;\n\n      this._queue.push({\n        item,\n        styles,\n        callback,\n      });\n\n      count += 1;\n    });\n  }\n\n  /**\n   * Return an array of Point instances representing the future positions of\n   * each item.\n   * @param {ShuffleItem[]} items Array of sorted shuffle items.\n   * @return {Point[]}\n   * @private\n   */\n  _getNextPositions(items) {\n    // If position data is going to be changed, add the item's size to the\n    // transformer to allow for calculations.\n    if (this.options.isCentered) {\n      const itemsData = items.map((item, i) => {\n        const itemSize = Shuffle.getSize(item.element, true);\n        const point = this._getItemPosition(itemSize);\n        return new Rect(point.x, point.y, itemSize.width, itemSize.height, i);\n      });\n\n      return this.getTransformedPositions(itemsData, this.containerWidth);\n    }\n\n    // If no transforms are going to happen, simply return an array of the\n    // future points of each item.\n    return items.map((item) => this._getItemPosition(Shuffle.getSize(item.element, true)));\n  }\n\n  /**\n   * Determine the location of the next item, based on its size.\n   * @param {{width: number, height: number}} itemSize Object with width and height.\n   * @return {Point}\n   * @private\n   */\n  _getItemPosition(itemSize) {\n    return getItemPosition({\n      itemSize,\n      positions: this.positions,\n      gridSize: this.colWidth,\n      total: this.cols,\n      threshold: this.options.columnThreshold,\n      buffer: this.options.buffer,\n    });\n  }\n\n  /**\n   * Mutate positions before they're applied.\n   * @param {Rect[]} itemRects Item data objects.\n   * @param {number} containerWidth Width of the containing element.\n   * @return {Point[]}\n   * @protected\n   */\n  getTransformedPositions(itemRects, containerWidth) {\n    return getCenteredPositions(itemRects, containerWidth);\n  }\n\n  /**\n   * Hides the elements that don't match our filter.\n   * @param {ShuffleItem[]} collection Collection to shrink.\n   * @private\n   */\n  _shrink(collection = this._getConcealedItems()) {\n    let count = 0;\n    collection.forEach((item) => {\n      function callback() {\n        item.applyCss(ShuffleItem.Css.HIDDEN.after);\n      }\n\n      // Continuing would add a transitionend event listener to the element, but\n      // that listener would not execute because the transform and opacity would\n      // stay the same.\n      // The callback is executed here because it is not guaranteed to be called\n      // after the transitionend event because the transitionend could be\n      // canceled if another animation starts.\n      if (item.isHidden) {\n        item.applyCss(ShuffleItem.Css.HIDDEN.before);\n        callback();\n        return;\n      }\n\n      item.scale = ShuffleItem.Scale.HIDDEN;\n      item.isHidden = true;\n\n      const styles = this.getStylesForTransition(item, ShuffleItem.Css.HIDDEN.before);\n      styles.transitionDelay = `${this._getStaggerAmount(count)}ms`;\n\n      this._queue.push({\n        item,\n        styles,\n        callback,\n      });\n\n      count += 1;\n    });\n  }\n\n  /**\n   * Resize handler.\n   * @param {ResizeObserverEntry[]} entries\n   */\n  _handleResizeCallback(entries) {\n    // If shuffle is disabled, destroyed, don't do anything.\n    // You can still manually force a shuffle update with shuffle.update({ force: true }).\n    if (!this.isEnabled || this.isDestroyed) {\n      return;\n    }\n\n    // The reason ESLint disables this is because for..of generates a lot of extra\n    // code using Babel, but Shuffle no longer supports browsers that old, so\n    // nothing to worry about.\n    // eslint-disable-next-line no-restricted-syntax\n    for (const entry of entries) {\n      if (Math.round(entry.contentRect.width) !== Math.round(this.containerWidth)) {\n        // If there was already an animation waiting, cancel it.\n        cancelAnimationFrame(this._rafId);\n        // Offload updating the DOM until the browser is ready.\n        this._rafId = requestAnimationFrame(this.update.bind(this));\n      }\n    }\n  }\n\n  /**\n   * Returns styles which will be applied to the an item for a transition.\n   * @param {ShuffleItem} item Item to get styles for. Should have updated\n   *   scale and point properties.\n   * @param {Object} styleObject Extra styles that will be used in the transition.\n   * @return {!Object} Transforms for transitions, left/top for animate.\n   * @protected\n   */\n  getStylesForTransition(item, styleObject) {\n    // Clone the object to avoid mutating the original.\n    const styles = { ...styleObject };\n\n    if (this.options.useTransforms) {\n      const sign = this.options.isRTL ? '-' : '';\n      const x = this.options.roundTransforms ? Math.round(item.point.x) : item.point.x;\n      const y = this.options.roundTransforms ? Math.round(item.point.y) : item.point.y;\n      styles.transform = `translate(${sign}${x}px, ${y}px) scale(${item.scale})`;\n    } else {\n      if (this.options.isRTL) {\n        styles.right = `${item.point.x}px`;\n      } else {\n        styles.left = `${item.point.x}px`;\n      }\n      styles.top = `${item.point.y}px`;\n    }\n\n    return styles;\n  }\n\n  /**\n   * Listen for the transition end on an element and execute the itemCallback\n   * when it finishes.\n   * @param {Element} element Element to listen on.\n   * @param {function} itemCallback Callback for the item.\n   * @param {function} done Callback to notify `parallel` that this one is done.\n   */\n  _whenTransitionDone(element, itemCallback, done) {\n    const id = onTransitionEnd(element, (evt) => {\n      itemCallback();\n      done(null, evt);\n    });\n\n    this._transitions.push(id);\n  }\n\n  /**\n   * Return a function which will set CSS styles and call the `done` function\n   * when (if) the transition finishes.\n   * @param {Object} opts Transition object.\n   * @return {function} A function to be called with a `done` function.\n   */\n  _getTransitionFunction(opts) {\n    return (done) => {\n      opts.item.applyCss(opts.styles);\n      this._whenTransitionDone(opts.item.element, opts.callback, done);\n    };\n  }\n\n  /**\n   * Execute the styles gathered in the style queue. This applies styles to elements,\n   * triggering transitions.\n   * @private\n   */\n  _processQueue() {\n    if (this.isTransitioning) {\n      this._cancelMovement();\n    }\n\n    const hasSpeed = this.options.speed > 0;\n    const hasQueue = this._queue.length > 0;\n\n    if (hasQueue && hasSpeed && this.isInitialized) {\n      this._startTransitions(this._queue);\n    } else if (hasQueue) {\n      this._styleImmediately(this._queue);\n      this._dispatch(Shuffle.EventType.LAYOUT);\n\n      // A call to layout happened, but none of the newly visible items will\n      // change position or the transition duration is zero, which will not trigger\n      // the transitionend event.\n    } else {\n      this._dispatch(Shuffle.EventType.LAYOUT);\n    }\n\n    // Remove everything in the style queue\n    this._queue.length = 0;\n  }\n\n  /**\n   * Wait for each transition to finish, the emit the layout event.\n   * @param {Object[]} transitions Array of transition objects.\n   */\n  _startTransitions(transitions) {\n    // Set flag that shuffle is currently in motion.\n    this.isTransitioning = true;\n\n    // Create an array of functions to be called.\n    const callbacks = transitions.map((obj) => this._getTransitionFunction(obj));\n\n    parallel(callbacks, this._movementFinished.bind(this));\n  }\n\n  _cancelMovement() {\n    // Remove the transition end event for each listener.\n    this._transitions.forEach(cancelTransitionEnd);\n\n    // Reset the array.\n    this._transitions.length = 0;\n\n    // Show it's no longer active.\n    this.isTransitioning = false;\n  }\n\n  /**\n   * Apply styles without a transition.\n   * @param {Object[]} objects Array of transition objects.\n   * @private\n   */\n  _styleImmediately(objects) {\n    if (objects.length) {\n      const elements = objects.map((obj) => obj.item.element);\n\n      Shuffle._skipTransitions(elements, () => {\n        objects.forEach((obj) => {\n          obj.item.applyCss(obj.styles);\n          obj.callback();\n        });\n      });\n    }\n  }\n\n  _movementFinished() {\n    this._transitions.length = 0;\n    this.isTransitioning = false;\n    this._dispatch(Shuffle.EventType.LAYOUT);\n  }\n\n  /**\n   * The magic. This is what makes the plugin 'shuffle'\n   * @param {string|string[]|function(Element):boolean} [category] Category to filter by.\n   *     Can be a function, string, or array of strings.\n   * @param {SortOptions} [sortOptions] A sort object which can sort the visible set\n   */\n  filter(category, sortOptions) {\n    if (!this.isEnabled) {\n      return;\n    }\n\n    if (!category || (category && category.length === 0)) {\n      category = Shuffle.ALL_ITEMS; // eslint-disable-line no-param-reassign\n    }\n\n    this._filter(category);\n\n    // Shrink each hidden item\n    this._shrink();\n\n    // How many visible elements?\n    this._updateItemCount();\n\n    // Update transforms on visible elements so they will animate to their new positions.\n    this.sort(sortOptions);\n  }\n\n  /**\n   * Gets the visible elements, sorts them, and passes them to layout.\n   * @param {SortOptions} [sortOptions] The options object to pass to `sorter`.\n   */\n  sort(sortOptions = this.lastSort) {\n    if (!this.isEnabled) {\n      return;\n    }\n\n    this._resetCols();\n\n    const items = sorter(this._getFilteredItems(), sortOptions);\n    this.sortedItems = items;\n\n    this._layout(items);\n\n    // `_layout` always happens after `_shrink`, so it's safe to process the style\n    // queue here with styles from the shrink method.\n    this._processQueue();\n\n    // Adjust the height of the container.\n    this._setContainerSize();\n\n    this.lastSort = sortOptions;\n  }\n\n  /**\n   * Reposition everything.\n   * @param {object} options options object\n   * @param {boolean} [options.recalculateSizes=true] Whether to calculate column, gutter, and container widths again.\n   * @param {boolean} [options.force=false] By default, `update` does nothing if the instance is disabled. Setting this\n   *    to true forces the update to happen regardless.\n   */\n  update({ recalculateSizes = true, force = false } = {}) {\n    if (this.isEnabled || force) {\n      if (recalculateSizes) {\n        this._setColumns();\n      }\n\n      // Layout items\n      this.sort();\n    }\n  }\n\n  /**\n   * Use this instead of `update()` if you don't need the columns and gutters updated\n   * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations\n   * could be off.\n   */\n  layout() {\n    this.update({\n      recalculateSizes: true,\n    });\n  }\n\n  /**\n   * New items have been appended to shuffle. Mix them in with the current\n   * filter or sort status.\n   * @param {Element[]} newItems Collection of new items.\n   */\n  add(newItems) {\n    const items = arrayUnique(newItems).map((el) => new ShuffleItem(el, this.options.isRTL));\n\n    // Add classes and set initial positions.\n    this._initItems(items);\n\n    // Determine which items will go with the current filter.\n    this._resetCols();\n\n    const allItems = this._mergeNewItems(items);\n    const sortedItems = sorter(allItems, this.lastSort);\n    const allSortedItemsSet = this._filter(this.lastFilter, sortedItems);\n\n    const isNewItem = (item) => items.includes(item);\n    const applyHiddenState = (item) => {\n      item.scale = ShuffleItem.Scale.HIDDEN;\n      item.isHidden = true;\n      item.applyCss(ShuffleItem.Css.HIDDEN.before);\n      item.applyCss(ShuffleItem.Css.HIDDEN.after);\n    };\n\n    // Layout all items again so that new items get positions.\n    // Synchonously apply positions.\n    const itemPositions = this._getNextPositions(allSortedItemsSet.visible);\n    allSortedItemsSet.visible.forEach((item, i) => {\n      if (isNewItem(item)) {\n        item.point = itemPositions[i];\n        applyHiddenState(item);\n        item.applyCss(this.getStylesForTransition(item, {}));\n      }\n    });\n\n    allSortedItemsSet.hidden.forEach((item) => {\n      if (isNewItem(item)) {\n        applyHiddenState(item);\n      }\n    });\n\n    // Cause layout so that the styles above are applied.\n    this.element.offsetWidth; // eslint-disable-line no-unused-expressions\n\n    // Add transition to each item.\n    this.setItemTransitions(items);\n\n    // Update the list of items.\n    this.items = this._mergeNewItems(items);\n\n    // Update layout/visibility of new and old items.\n    this.filter(this.lastFilter);\n  }\n\n  /**\n   * Disables shuffle from updating dimensions and layout on resize\n   */\n  disable() {\n    this.isEnabled = false;\n  }\n\n  /**\n   * Enables shuffle again\n   * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters\n   */\n  enable(isUpdateLayout = true) {\n    this.isEnabled = true;\n    if (isUpdateLayout) {\n      this.update();\n    }\n  }\n\n  /**\n   * Remove 1 or more shuffle items.\n   * @param {Element[]} elements An array containing one or more\n   *     elements in shuffle\n   * @return {Shuffle} The shuffle instance.\n   */\n  remove(elements) {\n    if (!elements.length) {\n      return;\n    }\n\n    const collection = arrayUnique(elements);\n\n    const oldItems = collection.map((element) => this.getItemByElement(element)).filter((item) => !!item);\n\n    const handleLayout = () => {\n      this._disposeItems(oldItems);\n\n      // Remove the collection in the callback\n      collection.forEach((element) => {\n        element.parentNode.removeChild(element);\n      });\n\n      this._dispatch(Shuffle.EventType.REMOVED, { collection });\n    };\n\n    // Hide collection first.\n    this._toggleFilterClasses({\n      visible: [],\n      hidden: oldItems,\n    });\n\n    this._shrink(oldItems);\n\n    this.sort();\n\n    // Update the list of items here because `remove` could be called again\n    // with an item that is in the process of being removed.\n    this.items = this.items.filter((item) => !oldItems.includes(item));\n    this._updateItemCount();\n\n    this.once(Shuffle.EventType.LAYOUT, handleLayout);\n  }\n\n  /**\n   * Retrieve a shuffle item by its element.\n   * @param {Element} element Element to look for.\n   * @return {?ShuffleItem} A shuffle item or undefined if it's not found.\n   */\n  getItemByElement(element) {\n    return this.items.find((item) => item.element === element);\n  }\n\n  /**\n   * Dump the elements currently stored and reinitialize all child elements which\n   * match the `itemSelector`.\n   */\n  resetItems() {\n    // Remove refs to current items.\n    this._disposeItems(this.items);\n    this.isInitialized = false;\n\n    // Find new items in the DOM.\n    this.items = this._getItems();\n\n    // Set initial styles on the new items.\n    this._initItems(this.items);\n\n    this.once(Shuffle.EventType.LAYOUT, () => {\n      // Add transition to each item.\n      this.setItemTransitions(this.items);\n      this.isInitialized = true;\n    });\n\n    // Lay out all items.\n    this.filter(this.lastFilter);\n  }\n\n  /**\n   * Destroys shuffle, removes events, styles, and classes\n   */\n  destroy() {\n    this._cancelMovement();\n    if (this._resizeObserver) {\n      this._resizeObserver.unobserve(this.element);\n      this._resizeObserver = null;\n    }\n\n    // Reset container styles\n    this.element.classList.remove('shuffle');\n    this.element.removeAttribute('style');\n\n    // Reset individual item styles\n    this._disposeItems(this.items);\n\n    this.items.length = 0;\n    this.sortedItems.length = 0;\n    this._transitions.length = 0;\n\n    // Null DOM references\n    this.options.sizer = null;\n    this.element = null;\n\n    // Set a flag so if a debounced resize has been triggered,\n    // it can first check if it is actually isDestroyed and not doing anything\n    this.isDestroyed = true;\n    this.isEnabled = false;\n  }\n\n  /**\n   * Returns the outer width of an element, optionally including its margins.\n   *\n   * There are a few different methods for getting the width of an element, none of\n   * which work perfectly for all Shuffle's use cases.\n   *\n   * 1. getBoundingClientRect() `left` and `right` properties.\n   *   - Accounts for transform scaled elements, making it useless for Shuffle\n   *   elements which have shrunk.\n   * 2. The `offsetWidth` property.\n   *   - This value stays the same regardless of the elements transform property,\n   *   however, it does not return subpixel values.\n   * 3. getComputedStyle()\n   *   - This works great Chrome, Firefox, Safari, but IE<=11 does not include\n   *   padding and border when box-sizing: border-box is set, requiring a feature\n   *   test and extra work to add the padding back for IE and other browsers which\n   *   follow the W3C spec here.\n   *\n   * @param {Element} element The element.\n   * @param {boolean} [includeMargins=false] Whether to include margins.\n   * @return {{width: number, height: number}} The width and height.\n   */\n  static getSize(element, includeMargins = false) {\n    // Store the styles so that they can be used by others without asking for it again.\n    const styles = window.getComputedStyle(element, null);\n    let width = getNumberStyle(element, 'width', styles);\n    let height = getNumberStyle(element, 'height', styles);\n\n    if (includeMargins) {\n      const marginLeft = getNumberStyle(element, 'marginLeft', styles);\n      const marginRight = getNumberStyle(element, 'marginRight', styles);\n      const marginTop = getNumberStyle(element, 'marginTop', styles);\n      const marginBottom = getNumberStyle(element, 'marginBottom', styles);\n      width += marginLeft + marginRight;\n      height += marginTop + marginBottom;\n    }\n\n    return {\n      width,\n      height,\n    };\n  }\n\n  /**\n   * Change a property or execute a function which will not have a transition\n   * @param {Element[]} elements DOM elements that won't be transitioned.\n   * @param {function} callback A function which will be called while transition\n   *     is set to 0ms.\n   * @private\n   */\n  static _skipTransitions(elements, callback) {\n    const zero = '0ms';\n\n    // Save current duration and delay.\n    const data = elements.map((element) => {\n      const { style } = element;\n      const duration = style.transitionDuration;\n      const delay = style.transitionDelay;\n\n      // Set the duration to zero so it happens immediately\n      style.transitionDuration = zero;\n      style.transitionDelay = zero;\n\n      return {\n        duration,\n        delay,\n      };\n    });\n\n    callback();\n\n    // Cause forced synchronous layout.\n    elements[0].offsetWidth; // eslint-disable-line no-unused-expressions\n\n    // Put the duration back\n    elements.forEach((element, i) => {\n      element.style.transitionDuration = data[i].duration;\n      element.style.transitionDelay = data[i].delay;\n    });\n  }\n}\n\nShuffle.ShuffleItem = ShuffleItem;\n\nShuffle.ALL_ITEMS = 'all';\nShuffle.FILTER_ATTRIBUTE_KEY = 'groups';\n\n/** @enum {string} */\nShuffle.EventType = {\n  LAYOUT: 'shuffle:layout',\n  REMOVED: 'shuffle:removed',\n};\n\n/** @enum {string} */\nShuffle.Classes = Classes;\n\n/** @enum {string} */\nShuffle.FilterMode = {\n  ANY: 'any',\n  ALL: 'all',\n};\n\n// Overrideable options\nShuffle.options = {\n  // Initial filter group.\n  group: Shuffle.ALL_ITEMS,\n\n  // Transition/animation speed (milliseconds).\n  speed: 250,\n\n  // CSS easing function to use.\n  easing: 'cubic-bezier(0.4, 0.0, 0.2, 1)',\n\n  // e.g. '.picture-item'.\n  itemSelector: '*',\n\n  // Element or selector string. Use an element to determine the size of columns\n  // and gutters.\n  sizer: null,\n\n  // A static number or function that tells the plugin how wide the gutters\n  // between columns are (in pixels).\n  gutterWidth: 0,\n\n  // A static number or function that returns a number which tells the plugin\n  // how wide the columns are (in pixels).\n  columnWidth: 0,\n\n  // If your group is not json, and is comma delimited, you could set delimiter\n  // to ','.\n  delimiter: null,\n\n  // Useful for percentage based heights when they might not always be exactly\n  // the same (in pixels).\n  buffer: 0,\n\n  // Reading the width of elements isn't precise enough and can cause columns to\n  // jump between values.\n  columnThreshold: 0.01,\n\n  // Shuffle can be initialized with a sort object. It is the same object\n  // given to the sort method.\n  initialSort: null,\n\n  // Transition delay offset for each item in milliseconds.\n  staggerAmount: 15,\n\n  // Maximum stagger delay in milliseconds.\n  staggerAmountMax: 150,\n\n  // Whether to use transforms or absolute positioning.\n  useTransforms: true,\n\n  // Affects using an array with filter. e.g. `filter(['one', 'two'])`. With \"any\",\n  // the element passes the test if any of its groups are in the array. With \"all\",\n  // the element only passes if all groups are in the array.\n  // Note, this has no effect if you supply a custom filter function.\n  filterMode: Shuffle.FilterMode.ANY,\n\n  // Attempt to center grid items in each row.\n  isCentered: false,\n\n  // Attempt to align grid items to right.\n  isRTL: false,\n\n  // Whether to round pixel values used in translate(x, y). This usually avoids\n  // blurriness.\n  roundTransforms: true,\n};\n\nShuffle.Point = Point;\nShuffle.Rect = Rect;\n\n// Expose for testing. Hack at your own risk.\nShuffle.__sorter = sorter;\nShuffle.__getColumnSpan = getColumnSpan;\nShuffle.__getAvailablePositions = getAvailablePositions;\nShuffle.__getShortColumn = getShortColumn;\nShuffle.__getCenteredPositions = getCenteredPositions;\n\nexport default Shuffle;\n","/**\n * Hyphenates a javascript style string to a css one. For example:\n * MozBoxSizing -> -moz-box-sizing.\n * @param {string} str The string to hyphenate.\n * @return {string} The hyphenated string.\n */\nexport default function hyphenate(str) {\n  return str.replace(/([A-Z])/g, (str, m1) => `-${m1.toLowerCase()}`);\n}\n"],"names":["E","prototype","on","name","callback","ctx","e","this","push","fn","once","self","listener","off","apply","arguments","_","emit","data","slice","call","evtArr","i","len","length","evts","liveEvents","tinyEmitterModule","exports","tinyEmitter","TinyEmitter","noop","getNumber","value","parseFloat","Point","constructor","x","y","static","a","b","Rect","w","h","id","left","top","width","height","Classes","BASE","SHUFFLE_ITEM","VISIBLE","HIDDEN","ShuffleItem","element","isRTL","isVisible","isHidden","show","classList","remove","add","removeAttribute","hide","setAttribute","init","addClasses","applyCss","Css","INITIAL","DIRECTION","rtl","ltr","scale","Scale","point","classes","forEach","className","removeClasses","obj","Object","keys","key","style","dispose","position","visibility","willChange","right","before","opacity","after","transitionDelay","testComputedSize","document","body","documentElement","createElement","cssText","appendChild","window","getComputedStyle","Math","round","removeChild","getNumberStyle","styles","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","paddingLeft","paddingRight","borderLeftWidth","borderRightWidth","defaults","reverse","by","compare","randomize","sorter","arr","options","opts","original","Array","from","revert","array","n","floor","random","temp","sort","valA","valB","undefined","transitions","eventName","count","cancelTransitionEnd","removeEventListener","onTransitionEnd","evt","currentTarget","target","addEventListener","arrayMax","max","getColumnSpan","itemWidth","columnWidth","columns","threshold","columnSpan","abs","min","ceil","getAvailablePositions","positions","available","getShortColumn","buffer","minPosition","getCenteredPositions","itemRects","containerWidth","rowMap","itemRect","rects","rows","centeredRows","lastItem","end","offset","finalRects","canMove","newRects","every","r","newRect","noOverlap","some","intersects","intersectingRect","rowIndex","findIndex","items","includes","splice","concat","flat","map","arrayUnique","Set","Shuffle","super","lastSort","group","ALL_ITEMS","lastFilter","isEnabled","isDestroyed","isInitialized","_transitions","isTransitioning","_queue","el","_getElementOption","TypeError","_init","_getItems","sortedItems","sizer","_initItems","readyState","layout","bind","onLoad","containerCss","getSize","_validateStyles","_setColumns","filter","initialSort","_rafId","_resizeObserver","ResizeObserver","_handleResizeCallback","observe","offsetWidth","setItemTransitions","transition","speed","easing","option","querySelector","nodeType","jquery","overflow","_filter","category","collection","set","_getFilteredSets","_toggleFilterClasses","visible","hidden","item","_doesPassFilter","attr","dataset","FILTER_ATTRIBUTE_KEY","delimiter","split","JSON","parse","testCategory","isArray","filterMode","FilterMode","ANY","_ref","_disposeItems","_updateItemCount","visibleItems","_getFilteredItems","positionProps","useTransforms","cssProps","k","replace","str","m1","toLowerCase","properties","join","transitionDuration","transitionTimingFunction","transitionProperty","children","matches","itemSelector","_mergeNewItems","indexOf","_getConcealedItems","_getColumnSize","gutterSize","size","_getGutterSize","gutterWidth","gutter","calculatedColumns","columnThreshold","cols","colWidth","_setContainerSize","_getContainerSize","_getStaggerAmount","index","staggerAmount","staggerAmountMax","_dispatch","shuffle","_resetCols","_layout","itemPositions","_getNextPositions","equals","getStylesForTransition","isCentered","itemsData","itemSize","_getItemPosition","getTransformedPositions","gridSize","total","span","setY","shortColumnIndex","setHeight","getItemPosition","_shrink","entries","entry","contentRect","cancelAnimationFrame","requestAnimationFrame","update","styleObject","sign","roundTransforms","transform","_whenTransitionDone","itemCallback","done","_getTransitionFunction","_processQueue","_cancelMovement","hasSpeed","hasQueue","_startTransitions","_styleImmediately","EventType","LAYOUT","fns","context","pending","finished","results","maybeDone","err","result","parallel","_movementFinished","objects","elements","_skipTransitions","sortOptions","recalculateSizes","force","newItems","allSortedItemsSet","isNewItem","applyHiddenState","disable","enable","isUpdateLayout","oldItems","getItemByElement","parentNode","REMOVED","find","resetItems","destroy","unobserve","includeMargins","duration","delay","ALL","__sorter","__getColumnSpan","__getAvailablePositions","__getShortColumn","__getCenteredPositions"],"mappings":"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"}