{"version":3,"file":"shuffle.mjs","names":["id","#count","#uniqueId","#transitions","#transitionManager","#queue","#getElementOption","#getItems","#validateStyles","#setColumns","#rafId","#resizeObserver","#handleResizeCallback","#getFilteredSets","#doesPassFilter","#getFilteredItems","#getGutterSize","#getColumnSize","#getContainerSize","#getNextPositions","#getStaggerAmount","#getItemPosition","#getConcealedItems","#whenTransitionDone","#cancelMovement","#startTransitions","#getTransitionFunction","#movementFinished","#filter","#shrink","#updateItemCount","#resetCols","#layout","#processQueue","#setContainerSize","#mergeNewItems"],"sources":["../src/tiny-emitter.ts","../src/parallel.ts","../src/helpers.ts","../src/point.ts","../src/rect.ts","../src/constants.ts","../src/shuffle-item.ts","../src/sorter.ts","../src/transition-manager.ts","../src/layout.ts","../src/shuffle.ts"],"sourcesContent":["// oxlint-disable typescript/no-unsafe-function-type, typescript/ban-types, typescript/no-explicit-any, typescript/no-unsafe-assignment\n/**\n * @fileoverview copy of `tiny-emitter` on npm, but converted to ESM\n */\n\nexport class TinyEmitter {\n  handlers?: Record<string, { fn: Function & { onceCb?: Function }; ctx?: any }[]>;\n\n  on(event: string, callback: Function, ctx?: any): this {\n    const handlers = this.handlers ?? (this.handlers = {});\n\n    (handlers[event] || (handlers[event] = [])).push({\n      fn: callback,\n      ctx,\n    });\n\n    return this;\n  }\n\n  once(event: string, callback: Function, ctx?: any): this {\n    // oxlint-disable-next-line typescript/no-this-alias, unicorn/no-this-assignment\n    const self = this;\n    function listener() {\n      self.off(event, listener);\n      // oxlint-disable-next-line prefer-rest-params\n      callback.apply(ctx, arguments);\n    }\n\n    listener.onceCb = callback;\n    return this.on(event, listener, ctx);\n  }\n\n  emit(event: string, ...args: any[]): this {\n    const data = args;\n    const evtArr = [...((this.handlers ?? (this.handlers = {}))[event] || [])];\n    let i = 0;\n    const len = evtArr.length;\n\n    for (i; i < len; i += 1) {\n      evtArr[i].fn.apply(evtArr[i].ctx, data);\n    }\n\n    return this;\n  }\n\n  off(event: string, callback?: Function): this {\n    const handlers = this.handlers ?? (this.handlers = {});\n    const evts = handlers[event];\n    const liveEvents = [];\n\n    if (evts && callback) {\n      for (let i = 0, len = evts.length; i < len; i += 1) {\n        if (evts[i].fn !== callback && evts[i].fn.onceCb !== callback) {\n          liveEvents.push(evts[i]);\n        }\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    if (liveEvents.length > 0) {\n      handlers[event] = liveEvents;\n    } else {\n      // oxlint-disable-next-line typescript/no-dynamic-delete\n      delete handlers[event];\n    }\n\n    return this;\n  }\n}\n","// oxlint-disable unicorn/explicit-length-check, no-param-reassign, no-plusplus\n// Copied and converted from https://github.com/component/array-parallel/blob/f9240097cb1edf8432111d2bf6cb6eb600da34c2/index.js\n\n/**\n * Execute an array of functions in parallel.\n * Calls the callback with an error if any function fails,\n * otherwise calls it with null and an array of results.\n */\nexport function parallel<ResultType>(\n  fns: ((done: (err: Error | null, result?: ResultType) => void) => void)[],\n  context?: unknown,\n  callback?: (err: Error | null, results?: ResultType[]) => void,\n): void {\n  if (!callback) {\n    if (typeof context === 'function') {\n      callback = context as (err: Error | null, results?: ResultType[]) => void;\n      context = null;\n    } else {\n      callback = noop;\n    }\n  }\n\n  let pending = fns && fns.length;\n\n  if (!pending) {\n    callback(null, []);\n    return;\n  }\n\n  let finished = false;\n  // oxlint-disable-next-line unicorn/no-new-array\n  const results = new Array(pending);\n\n  for (let i = 0, len = fns.length; i < len; i++) {\n    const fn = fns[i];\n    fn.call(context, maybeDone(i));\n  }\n\n  function maybeDone(i: number) {\n    return function onDoneCheck(err: Error | null, result?: ResultType) {\n      if (finished) {\n        return;\n      }\n\n      if (err) {\n        callback!(err, results);\n        finished = true;\n        return;\n      }\n\n      results[i] = result;\n\n      if (!--pending) {\n        callback!(null, results);\n      }\n    };\n  }\n}\n\nfunction noop(): void {\n  // no-op\n}\n","import type { QueueItem } from './types';\n\n/**\n * Change a property or execute a function which will not have a transition\n * @param elements DOM elements that won't be transitioned.\n * @param callback A function which will be called while transition is set to 0ms.\n */\nexport function skipTransitions(elements: HTMLElement[], callback: () => void): void {\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  // oxlint-disable-next-line no-unused-expressions\n  elements[0].offsetWidth;\n\n  // Put the duration back\n  for (let i = 0; i < elements.length; i += 1) {\n    elements[i].style.transitionDuration = data[i].duration;\n    elements[i].style.transitionDelay = data[i].delay;\n  }\n}\n\n/**\n * Apply styles without a transition.\n * Array of transition objects.\n */\nexport function styleImmediately(objects: QueueItem[]): void {\n  if (objects.length > 0) {\n    const elements = objects.map((obj) => obj.item.element);\n\n    skipTransitions(elements, () => {\n      for (const obj of objects) {\n        obj.item.applyCss(obj.styles);\n        obj.callback();\n      }\n    });\n  }\n}\n\nexport function arrayUnique<Item>(items: Item[]): Item[] {\n  return [...new Set(items)];\n}\n\nconst EXPECTED_WIDTH = 10;\nlet value: boolean | null = null;\n\nexport function testComputedSize(): boolean {\n  if (value !== null) {\n    return value;\n  }\n\n  const element = document.body || document.documentElement;\n  const div = document.createElement('div');\n  div.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';\n  element.append(div);\n\n  const { width } = globalThis.getComputedStyle(div, null);\n  // Fix for issue #314\n  value = Math.round(getNumber(width)) === EXPECTED_WIDTH;\n\n  div.remove();\n\n  return value;\n}\n\nconst DEFAULT_NUMBER = 0;\n\n/**\n * Always returns a numeric value, given a value. Logic from jQuery's `isNumeric`.\n * @param value Possibly numeric value.\n * @return `value` or zero if `value` isn't numeric.\n */\n\nexport function getNumber(value: unknown): number {\n  return Number.parseFloat(String(value)) || DEFAULT_NUMBER;\n}\n\n/**\n * Retrieve the computed style for an element, parsed as a float.\n * @param element Element to get style for.\n * @param style Style property.\n * @param styles Optionally include clean styles to use instead of asking for\n * them again.\n * @return The parsed computed value or zero if that fails because IE will\n * return 'auto' when the element doesn't have margins instead of the computed style.\n */\nexport function getNumberStyle(\n  element: Element,\n  style: keyof CSSStyleDeclaration,\n  styles: CSSStyleDeclaration = globalThis.getComputedStyle(element, null),\n): number {\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/**\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 The element.\n * @param includeMargins Whether to include margins.\n * @return The width and height.\n */\nexport function getSize(element: HTMLElement, includeMargins = false): { width: number; height: number } {\n  // Store the styles so that they can be used by others without asking for it again.\n  const styles = globalThis.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","import { getNumber } from './helpers';\n\nexport class Point {\n  x: number;\n  y: number;\n\n  /**\n   * Represents a coordinate pair.\n   * @param x X coordinate.\n   * @param y Y coordinate.\n   */\n  constructor(x?: number | string, y?: number | string) {\n    this.x = getNumber(x);\n    this.y = getNumber(y);\n  }\n\n  /**\n   * Whether two points are equal.\n   * @param pointA Point A.\n   * @param pointB Point B.\n   * @return Whether the points are equal.\n   */\n  static equals(pointA: Point, pointB: Point): boolean {\n    return pointA.x === pointB.x && pointA.y === pointB.y;\n  }\n}\n","export class Rect {\n  id: number;\n  left: number;\n  top: number;\n  width: number;\n  height: number;\n\n  /**\n   * Class for representing rectangular regions.\n   * https://github.com/google/closure-library/blob/master/closure/goog/math/rect.js\n   * @param x Left.\n   * @param y Top.\n   * @param width Width.\n   * @param height Height.\n   * @param id Identifier.\n   */\n  constructor(x: number, y: number, width: number, height: number, id: number) {\n    this.id = id;\n    this.left = x;\n    this.top = y;\n    this.width = width;\n    this.height = height;\n  }\n\n  /**\n   * Returns whether two rectangles intersect.\n   * @param rectA A rectangle.\n   * @param rectB A rectangle.\n   * @return Whether a and b intersect.\n   */\n  static intersects(rectA: Rect, rectB: Rect): boolean {\n    return (\n      rectA.left < rectB.left + rectB.width &&\n      rectB.left < rectA.left + rectA.width &&\n      rectA.top < rectB.top + rectB.height &&\n      rectB.top < rectA.top + rectA.height\n    );\n  }\n}\n","import type { FilterModeOptions, ShuffleEventMap, ShuffleOptions } from './types';\n\nexport const Classes = {\n  BASE: 'shuffle',\n  SHUFFLE_ITEM: 'shuffle-item',\n  VISIBLE: 'shuffle-item--visible',\n  HIDDEN: 'shuffle-item--hidden',\n} as const;\n\nexport const ALL_ITEMS = 'all';\n\nexport const FILTER_ATTRIBUTE_KEY = 'groups';\n\nexport const FilterMode: {\n  ANY: 'any';\n  ALL: 'all';\n} = {\n  ANY: 'any',\n  ALL: 'all',\n} satisfies Record<string, FilterModeOptions>;\n\nexport const EventType: {\n  LAYOUT: 'shuffle:layout';\n  REMOVED: 'shuffle:removed';\n} = {\n  LAYOUT: 'shuffle:layout',\n  REMOVED: 'shuffle:removed',\n} satisfies Record<string, keyof ShuffleEventMap>;\n\nexport const DEFAULT_OPTIONS: ShuffleOptions = {\n  // Initial filter group.\n  group: 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: 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} as const;\n","import { Point } from './point';\nimport { Classes } from './constants';\nimport type { FilterSet, InlineCssStyles, ShuffleItemCss } from './types';\n\nlet id = 0;\n\nexport class ShuffleItem {\n  id: number;\n  element: HTMLElement;\n  isRTL: boolean;\n  isVisible: boolean;\n  isHidden: boolean;\n  scale = 1;\n  point: Point = new Point();\n\n  constructor(element: HTMLElement, isRTL?: boolean) {\n    id += 1;\n    this.id = id;\n    this.element = element;\n\n    /**\n     * Set correct direction of item\n     */\n    this.isRTL = Boolean(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(): void {\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(): void {\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(): void {\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: string[]): void {\n    for (const className of classes) {\n      this.element.classList.add(className);\n    }\n  }\n\n  removeClasses(classes: string[]): void {\n    for (const className of classes) {\n      this.element.classList.remove(className);\n    }\n  }\n\n  applyCss(obj: InlineCssStyles): void {\n    for (const [key, value] of Object.entries(obj)) {\n      // @ts-expect-error shrug\n      this.element.style[key] = String(value);\n    }\n  }\n\n  dispose(): void {\n    this.removeClasses([Classes.HIDDEN, Classes.VISIBLE, Classes.SHUFFLE_ITEM]);\n\n    this.element.removeAttribute('style');\n    // @ts-expect-error nullifying for garbage collection\n    this.element = null;\n  }\n\n  static Css: ShuffleItemCss = {\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\n  static Scale = {\n    VISIBLE: 1,\n    HIDDEN: 0.001,\n  };\n}\n\n/**\n * Toggles the visible and hidden class names.\n * @param Object with visible and hidden arrays.\n */\nexport function toggleFilterClasses({ visible, hidden }: FilterSet): void {\n  for (const item of visible) {\n    item.show();\n  }\n\n  for (const item of hidden) {\n    item.hide();\n  }\n}\n\n/**\n * Set the initial css for each item\n * @param items Set to initialize.\n */\nexport function initItems(items: ShuffleItem[]): void {\n  for (const item of items) {\n    item.init();\n  }\n}\n\n/**\n * Remove element reference and styles.\n * @param items Set to dispose.\n */\nexport function disposeItems(items: ShuffleItem[]): void {\n  for (const item of items) {\n    item.dispose();\n  }\n}\n\nexport function applyHiddenState(item: ShuffleItem): void {\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","import type { ShuffleItem } from './shuffle-item';\nimport type { SortOptions } from './types';\n\n/**\n * Fisher-Yates shuffle.\n * http://stackoverflow.com/a/962890/373422\n * https://bost.ocks.org/mike/shuffle/\n * @param array Array to shuffle.\n * @return Randomly sorted array.\n */\nfunction randomize<Item>(array: Item[]): Item[] {\n  let count = array.length;\n\n  while (count) {\n    count -= 1;\n    const index = Math.floor(Math.random() * (count + 1));\n    const temp = array[index];\n    array[index] = array[count];\n    array[count] = 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} as const;\n\n/**\n * You can return `undefined` from the `by` function to revert to DOM order.\n * @param arr Array to sort.\n * @param options Sorting options.\n * @return The sorted array.\n */\nexport function sorter(arr: ShuffleItem[], options?: SortOptions | null): ShuffleItem[] {\n  // Handle invalid input gracefully\n  if (!Array.isArray(arr)) {\n    return [];\n  }\n\n  const opts = { ...defaults, ...options };\n  const original = [...arr];\n  let revert = false;\n\n  if (arr.length === 0) {\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    const sortBy = opts.by;\n    arr.sort((itemA, itemB) => {\n      // Exit early if we already know we want to revert\n      if (revert) {\n        return 0;\n      }\n\n      const itemAValue = itemA[opts.key];\n      const itemBValue = itemB[opts.key];\n      // @ts-expect-error the key is dynamic, but we know it will be a valid key of ShuffleItem\n      // oxlint-disable-next-line typescript/no-unsafe-assignment\n      const valA = sortBy(itemAValue);\n      // @ts-expect-error dynamic key\n      // oxlint-disable-next-line typescript/no-unsafe-assignment\n      const valB = sortBy(itemBValue);\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","type TransitionEventCallback = (event: TransitionEvent) => void;\n\ninterface Transition {\n  element: HTMLElement;\n  listener: TransitionEventCallback;\n}\n\nexport class TransitionManager {\n  #transitions = new Map<string, Transition>();\n  #count = 0;\n\n  #uniqueId(): string {\n    this.#count += 1;\n    return `transitionend${this.#count}`;\n  }\n\n  waitForTransition(element: HTMLElement, callback: TransitionEventCallback): string {\n    const id = this.#uniqueId();\n    const listener = (event: TransitionEvent) => {\n      if (event.currentTarget === event.target) {\n        this.cancelTransition(id);\n        callback(event);\n      }\n    };\n\n    element.addEventListener('transitionend', listener as EventListener);\n    this.#transitions.set(id, { element, listener });\n\n    return id;\n  }\n\n  cancelTransition(id: string): boolean {\n    const entry = this.#transitions.get(id);\n    if (entry) {\n      entry.element.removeEventListener('transitionend', entry.listener as EventListener);\n      this.#transitions.delete(id);\n      return true;\n    }\n\n    return false;\n  }\n\n  cancelAll(): void {\n    for (const id of this.#transitions.keys()) {\n      this.cancelTransition(id);\n    }\n  }\n}\n\nexport function createTransitionManager(): TransitionManager {\n  return new TransitionManager();\n}\n","import { Point } from './point';\nimport { Rect } from './rect';\n\n/**\n * Determine the number of columns an items spans.\n * @param itemWidth Width of the item.\n * @param columnWidth Width of the column (includes gutter).\n * @param columns Total number of columns.\n * @param threshold A buffer value for the size of the column to fit.\n * @return The column span.\n */\nexport function getColumnSpan(itemWidth: number, columnWidth: number, columns: number, threshold: number): number {\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 positions The position array.\n * @param columnSpan The number of columns this current item spans.\n * @param columns The total columns in the grid.\n * @return An array of numbers representing the column set.\n */\nexport function getAvailablePositions(positions: number[], columnSpan: number, columns: number): number[] {\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 += 1) {\n    // Find the bigger value for each place it could fit.\n    available.push(Math.max(...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 positions The array to search for the smallest number.\n * @param buffer Optional buffer which is very useful when the height is a percentage of the width.\n * @return Index of the short column.\n */\nexport function getShortColumn(positions: number[], buffer: number): number {\n  const minPosition = Math.min(...positions);\n  for (let i = 0, len = positions.length; i < len; i += 1) {\n    if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {\n      return i;\n    }\n  }\n\n  return 0;\n}\n\ninterface ItemPositionParams {\n  /** Object with width and height. */\n  itemSize: { width: number; height: number };\n  /** Positions of the other current items. */\n  positions: number[];\n  /** The column width or row height. */\n  gridSize: number;\n  /** The total number of columns or rows. */\n  total: number;\n  /** Buffer value for the column to fit. */\n  threshold: number;\n  /** Vertical buffer for the height of items. */\n  buffer: number;\n}\n\n/**\n * Determine the location of the next item, based on its size.\n * @param params Object with itemSize, positions, gridSize, total, threshold, and buffer.\n * @return The point position for the item.\n */\nexport function getItemPosition({\n  itemSize,\n  positions,\n  gridSize,\n  total,\n  threshold,\n  buffer,\n}: ItemPositionParams): Point {\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 += 1) {\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 itemRects Item data objects.\n * @param containerWidth Width of the containing element.\n * @return An array of centered points.\n */\nexport function getCenteredPositions(itemRects: Rect[], containerWidth: number): Point[] {\n  const rowMap: Record<number, Rect[]> = {};\n\n  // Populate rows by their offset because items could jump between rows like:\n  // a   c\n  //  bbb\n  for (const itemRect of itemRects) {\n    if (rowMap[itemRect.top] === undefined) {\n      // Start of a new row.\n      rowMap[itemRect.top] = [itemRect];\n    } else {\n      // Push the point to the last row array.\n      rowMap[itemRect.top].push(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  const rects: Rect[] = [];\n  const rows: Rect[][] = [];\n  const centeredRows: Rect[][] = [];\n  for (const itemRects of Object.values(rowMap)) {\n    rows.push(itemRects);\n    const lastItem = itemRects.at(-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: Rect[] = [];\n      canMove = itemRects.every((comparisonRect) => {\n        const newRect = new Rect(\n          comparisonRect.left + offset,\n          comparisonRect.top,\n          comparisonRect.width,\n          comparisonRect.height,\n          comparisonRect.id,\n        );\n\n        // Check all current rects to make sure none overlap.\n        const noOverlap = !rects.some((rectangle) => Rect.intersects(newRect, rectangle));\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: Rect;\n      const hasOverlap = itemRects.some((itemRect) =>\n        rects.some((comparisonRect) => {\n          const intersects = Rect.intersects(itemRect, comparisonRect);\n          if (intersects) {\n            intersectingRect = comparisonRect;\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.push(...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    .toSorted((rowA, rowB) => rowA.id - rowB.id)\n    .map((itemRect) => new Point(itemRect.left, itemRect.top));\n}\n","import { TinyEmitter } from './tiny-emitter';\nimport { parallel } from './parallel';\nimport { Point } from './point';\nimport { Rect } from './rect';\nimport { ShuffleItem, applyHiddenState, disposeItems, initItems, toggleFilterClasses } from './shuffle-item';\nimport type {\n  ElementOption,\n  FilterArg,\n  FilterFunction,\n  FilterSet,\n  InlineCssStyles,\n  QueueItem,\n  ShuffleEventCallback,\n  ShuffleEventData,\n  ShuffleEventMap,\n  ShuffleOptions,\n  SortOptions,\n} from './types';\n\nimport { ALL_ITEMS, Classes, DEFAULT_OPTIONS, EventType, FILTER_ATTRIBUTE_KEY, FilterMode } from './constants';\nimport { arrayUnique, getNumberStyle, getSize, styleImmediately } from './helpers';\nimport { sorter } from './sorter';\nimport { createTransitionManager, type TransitionManager } from './transition-manager';\nimport { getItemPosition, getCenteredPositions } from './layout';\n\n// Re-export types for backward compatibility\nexport type {\n  SortOptions,\n  InlineCssStyles,\n  ShuffleOptions,\n  FilterFunction,\n  FilterArg,\n  ShuffleEventData,\n  ShuffleEventCallback,\n};\n\n// Used for unique instance variables\nlet id = 0;\n\nclass Shuffle extends TinyEmitter {\n  element: HTMLElement;\n  sizer: HTMLElement | null;\n  options: ShuffleOptions;\n  lastSort: SortOptions | null;\n  group: FilterArg;\n  lastFilter: FilterArg;\n  isEnabled: boolean;\n  isDestroyed: boolean;\n  isInitialized: boolean;\n  isTransitioning: boolean;\n  id: string;\n  items: ShuffleItem[];\n  sortedItems: ShuffleItem[];\n  visibleItems!: number;\n  cols!: number;\n  colWidth!: number;\n  containerWidth!: number;\n  positions!: number[];\n  #transitionManager: TransitionManager;\n  #queue: QueueItem[];\n  #rafId: number | null;\n  #resizeObserver: ResizeObserver | null = null;\n\n  /**\n   * Categorize, sort, and filter a responsive grid of items.\n   *\n   * @param element An element which is the parent container for the grid items.\n   * @param options Options object.\n   * @constructor\n   */\n  constructor(element: ElementOption, options: Partial<ShuffleOptions> = {}) {\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.#transitionManager = createTransitionManager();\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.items = this.#getItems();\n    this.sortedItems = this.items;\n\n    this.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    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 = globalThis.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.#resizeObserver = new ResizeObserver(this.#handleResizeCallback.bind(this));\n    this.#resizeObserver.observe(this.element);\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    // oxlint-disable-next-line no-unused-expressions\n    this.element.offsetWidth;\n    this.setItemTransitions(this.items);\n    this.element.style.transition = `height ${this.options.speed}ms ${this.options.easing}`;\n    this.isInitialized = true;\n  }\n\n  // Override TinyEmitter methods with proper types using conditional types\n  on<EventName extends keyof ShuffleEventMap>(\n    event: EventName,\n    callback: (data: ShuffleEventMap[EventName]) => void,\n    // oxlint-disable-next-line typescript/no-explicit-any\n    context?: any,\n  ): this;\n  // oxlint-disable-next-line typescript/no-explicit-any\n  on(event: string, callback: ShuffleEventCallback, context?: any): this;\n  // oxlint-disable-next-line typescript/no-explicit-any\n  on(event: string, callback: ShuffleEventCallback, context?: any): this {\n    return super.on(event, callback, context);\n  }\n\n  once<EventName extends keyof ShuffleEventMap>(\n    event: EventName,\n    callback: (data: ShuffleEventMap[EventName]) => void,\n    // oxlint-disable-next-line typescript/no-explicit-any\n    context?: any,\n  ): this;\n  // oxlint-disable-next-line typescript/no-explicit-any\n  once(event: string, callback: ShuffleEventCallback, context?: any): this;\n  // oxlint-disable-next-line typescript/no-explicit-any\n  once(event: string, callback: ShuffleEventCallback, context?: any): this {\n    return super.once(event, callback, context);\n  }\n\n  // emit(event: string, data: ShuffleEventData): this {\n  emit<EventName extends keyof ShuffleEventMap>(event: EventName, data: ShuffleEventMap[EventName]): this {\n    if (this.isDestroyed) {\n      return this;\n    }\n    return super.emit(event, data);\n  }\n\n  off(event: string, callback?: ShuffleEventCallback): this {\n    return super.off(event, callback);\n  }\n\n  /**\n   * Retrieve an element from an option.\n   * @param option The option to check.\n   * @return The plain element or null.\n   */\n  #getElementOption(option?: ElementOption | null): HTMLElement | null {\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 ? this.element.querySelector(option) : document.querySelector(option);\n    }\n\n    // Check for an element\n    if (option && 'nodeType' in option && option.nodeType && option.nodeType === 1) {\n      return option as HTMLElement;\n    }\n\n    // Check for jQuery object\n    if (option && 'jquery' in option) {\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 styles Key value pairs for position and overflow.\n   */\n  #validateStyles(styles: CSSStyleDeclaration): void {\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 category Category to filter by. If it's given, the last category will be used to filter the items.\n   * @param collection Optionally filter a collection. Defaults to all the items.\n   * @return Object with visible and hidden arrays.\n   */\n  #filter(category: FilterArg = this.lastFilter, collection: ShuffleItem[] = this.items): FilterSet {\n    const set = this.#getFilteredSets(category, collection);\n\n    // Individually add/remove hidden/visible classes\n    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 category Category or function to filter by.\n   * @param items A collection of items to filter.\n   */\n  #getFilteredSets(category: FilterArg, items: ShuffleItem[]): FilterSet {\n    let visible: ShuffleItem[] = [];\n    const hidden: ShuffleItem[] = [];\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      for (const item of items) {\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 category Category or function to filter by.\n   * @param element An element to test.\n   * @return Whether it passes the category/filter.\n   */\n  #doesPassFilter(category: FilterArg, element: HTMLElement): boolean {\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) as string[]);\n\n    function testCategory(category: string): boolean {\n      return keys.includes(category);\n    }\n\n    if (Array.isArray(category)) {\n      if (this.options.filterMode === FilterMode.ANY) {\n        return category.some(testCategory);\n      }\n      return category.every(testCategory);\n    }\n\n    return keys.includes(category);\n  }\n\n  /**\n   * Updates the visible item count.\n   */\n  #updateItemCount(): void {\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 items Shuffle items to set transitions on.\n   * @protected\n   */\n  setItemTransitions(items: ShuffleItem[]): void {\n    const { speed, easing } = this.options;\n    const positionProps = this.options.useTransforms ? ['transform'] : ['top', 'left'];\n\n    // Allow users to transition other properties if they exist in the `before`\n    // css mapping of the shuffle item.\n    const cssProps = Object.keys(ShuffleItem.Css.HIDDEN.before);\n    const properties = [...positionProps, ...cssProps].join(',');\n\n    for (const item of items) {\n      item.element.style.transitionDuration = `${speed}ms`;\n      // @ts-expect-error TS doesn't like that we are assigning `undefined`, but\n      // browsers don't have a problem with it.\n      item.element.style.transitionTimingFunction = easing;\n      item.element.style.transitionProperty = properties;\n    }\n  }\n\n  #getItems(): ShuffleItem[] {\n    return (\n      // oxlint-disable-next-line unicorn/prefer-spread `children` doesn't have `Symbol.iterator`\n      Array.from(this.element.children)\n        .filter((el) => el.matches(this.options.itemSelector!))\n        .map((el) => new ShuffleItem(el as HTMLElement, this.options.isRTL))\n    );\n  }\n\n  /**\n   * Combine the current items array with a new one and sort it by DOM order.\n   * @param items Items to track.\n   */\n  #mergeNewItems(items: ShuffleItem[]): ShuffleItem[] {\n    // oxlint-disable-next-line unicorn/prefer-spread `children` doesn't have `Symbol.iterator`\n    const children = Array.from(this.element.children);\n    return sorter([...this.items, ...items], {\n      by(element) {\n        return children.indexOf(element);\n      },\n    });\n  }\n\n  #getFilteredItems(): ShuffleItem[] {\n    return this.items.filter((item) => item.isVisible);\n  }\n\n  #getConcealedItems(): ShuffleItem[] {\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 containerWidth Size of the parent container.\n   * @param gutterSize Size of the gutters.\n   */\n  #getColumnSize(containerWidth: number, gutterSize: number): number {\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.sizer) {\n      size = Shuffle.getSize(this.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 containerWidth Size of the parent container.\n   */\n  #getGutterSize(containerWidth: number): number {\n    if (typeof this.options.gutterWidth === 'function') {\n      return this.options.gutterWidth(containerWidth);\n    }\n\n    if (this.sizer) {\n      return getNumberStyle(this.sizer, 'marginLeft');\n    }\n\n    if (this.options.gutterWidth) {\n      return this.options.gutterWidth;\n    }\n\n    return 0;\n  }\n\n  /**\n   * Calculate the number of columns to be used. Gets css if using sizer element.\n   * @param containerWidth Optionally specify a container width if it's already available.\n   */\n  #setColumns(containerWidth: number = Shuffle.getSize(this.element).width): void {\n    const gutter = this.#getGutterSize(containerWidth);\n    const columnWidth = this.#getColumnSize(containerWidth, gutter);\n    let calculatedColumns = (containerWidth + gutter) / columnWidth;\n    // TypeScript doesn't like comparing undefined to a number, but JS allows it\n    // and always returns `false`.\n    const threshold = this.options.columnThreshold!;\n\n    // Widths given from getStyles are not precise enough...\n    if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) < threshold) {\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(): void {\n    this.element.style.height = `${this.#getContainerSize()}px`;\n  }\n\n  /**\n   * Based on the column heights, it returns the biggest one.\n   */\n  #getContainerSize(): number {\n    return Math.max(...this.positions);\n  }\n\n  /**\n   * Get the clamped stagger amount.\n   * @param index Index of the item to be staggered.\n   */\n  #getStaggerAmount(index: number): number {\n    return Math.min(index * this.options.staggerAmount!, this.options.staggerAmountMax!);\n  }\n\n  /**\n   * Zeros out the y columns array, which is used to determine item placement.\n   */\n  #resetCols(): void {\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 items Array of items that will be shown/layed out in order in their array.\n   */\n  #layout(items: ShuffleItem[]): void {\n    const itemPositions = this.#getNextPositions(items);\n\n    let count = 0;\n    for (let i = 0; i < items.length; i += 1) {\n      const item = items[i];\n      const 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        continue;\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 items Array of sorted shuffle items.\n   */\n  #getNextPositions(items: ShuffleItem[]): Point[] {\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 itemSize Object with width and height.\n   */\n  #getItemPosition(itemSize: { width: number; height: number }): Point {\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 itemRects Item data objects.\n   * @param containerWidth Width of the containing element.\n   * @protected\n   */\n  getTransformedPositions(itemRects: Rect[], containerWidth: number): Point[] {\n    return getCenteredPositions(itemRects, containerWidth);\n  }\n\n  /**\n   * Hides the elements that don't match our filter.\n   * @param collection Collection to shrink.\n   */\n  #shrink(collection: ShuffleItem[] = this.#getConcealedItems()): void {\n    let count = 0;\n    for (const item of collection) {\n      const 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        continue;\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 entries\n   */\n  #handleResizeCallback(entries: ResizeObserverEntry[]): void {\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    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(() => {\n          this.update();\n        });\n      }\n    }\n  }\n\n  /**\n   * Returns styles which will be applied to the an item for a transition.\n   * @param item Item to get styles for. Should have updated scale and point properties.\n   * @param styleObject Extra styles that will be used in the transition.\n   * @return Transforms for transitions, left/top for animate.\n   */\n  protected getStylesForTransition(item: ShuffleItem, styleObject: InlineCssStyles): InlineCssStyles {\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 to listen on.\n   * @param itemCallback Callback for the item.\n   * @param done Callback to notify `parallel` that this one is done.\n   */\n  #whenTransitionDone(\n    element: HTMLElement,\n    itemCallback: () => void,\n    done: (err: null, evt: TransitionEvent) => void,\n  ): void {\n    this.#transitionManager.waitForTransition(element, (evt) => {\n      itemCallback();\n      done(null, evt);\n    });\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 opts Transition object.\n   */\n  #getTransitionFunction(opts: QueueItem): (done: (err: null, evt: TransitionEvent) => void) => void {\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   */\n  #processQueue(): void {\n    if (this.isTransitioning) {\n      this.#cancelMovement();\n    }\n\n    const hasSpeed = typeof this.options.speed === 'number' && 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      styleImmediately(this.#queue);\n      this.emit(Shuffle.EventType.LAYOUT, {\n        type: Shuffle.EventType.LAYOUT,\n        shuffle: this,\n      });\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.emit(Shuffle.EventType.LAYOUT, {\n        type: Shuffle.EventType.LAYOUT,\n        shuffle: this,\n      });\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   * Array of transition objects.\n   */\n  #startTransitions(transitions: QueueItem[]): void {\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(): void {\n    // Remove the transition end event for each listener.\n    this.#transitionManager.cancelAll();\n\n    // Show it's no longer active.\n    this.isTransitioning = false;\n  }\n\n  #movementFinished(): void {\n    this.isTransitioning = false;\n    this.emit(Shuffle.EventType.LAYOUT, {\n      type: Shuffle.EventType.LAYOUT,\n      shuffle: this,\n    });\n  }\n\n  /**\n   * The magic. This is what makes the plugin 'shuffle'\n   * @param category Category to filter by. Can be a function, string, or array of strings.\n   * @param sortOptions A sort object which can sort the visible set\n   */\n  filter(category?: FilterArg, sortOptions?: SortOptions | null): void {\n    if (!this.isEnabled) {\n      return;\n    }\n\n    if (!category || category.length === 0) {\n      // oxlint-disable-next-line no-param-reassign\n      category = Shuffle.ALL_ITEMS;\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 The options object to pass to `sorter`.\n   */\n  sort(sortOptions: SortOptions | null = this.lastSort): void {\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 options options object\n   * @param options.recalculateSizes Whether to calculate column, gutter, and container widths again.\n   * @param options.force By default, `update` does nothing if the instance is disabled. Setting this\n   *    to true forces the update to happen regardless.\n   */\n  update({\n    recalculateSizes = true,\n    force = false,\n  }: {\n    recalculateSizes?: boolean;\n    force?: boolean;\n  } = {}): void {\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(): void {\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 newItems Collection of new items.\n   */\n  add(newItems: HTMLElement[]): void {\n    const items = arrayUnique(newItems).map((el) => new ShuffleItem(el, this.options.isRTL));\n\n    // Add classes and set initial positions.\n    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    // Layout all items again so that new items get positions.\n    // Synchronously apply positions.\n    const itemPositions = this.#getNextPositions(allSortedItemsSet.visible);\n    for (let i = 0; i < allSortedItemsSet.visible.length; i += 1) {\n      const item = allSortedItemsSet.visible[i];\n      if (items.includes(item)) {\n        item.point = itemPositions[i];\n        applyHiddenState(item);\n        item.applyCss(this.getStylesForTransition(item, {}));\n      }\n    }\n\n    for (const item of allSortedItemsSet.hidden) {\n      if (items.includes(item)) {\n        applyHiddenState(item);\n      }\n    }\n\n    // Cause layout so that the styles above are applied.\n    // oxlint-disable-next-line no-unused-expressions\n    this.element.offsetWidth;\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(): void {\n    this.isEnabled = false;\n  }\n\n  /**\n   * Enables shuffle again\n   * @param isUpdateLayout if undefined, shuffle will update columns and gutters\n   */\n  enable(isUpdateLayout = true): void {\n    this.isEnabled = true;\n    if (isUpdateLayout) {\n      this.update();\n    }\n  }\n\n  /**\n   * Remove 1 or more shuffle items.\n   * @param elements An array containing one or more elements in shuffle\n   */\n  remove(elements: HTMLElement[]): void {\n    if (elements.length === 0) {\n      return;\n    }\n\n    const collection = arrayUnique(elements);\n\n    const oldItems = collection.map((element) => this.getItemByElement(element)).filter(Boolean) as ShuffleItem[];\n\n    const handleLayout = () => {\n      disposeItems(oldItems);\n\n      // Remove the collection in the callback\n      for (const element of collection) {\n        element.remove();\n      }\n\n      this.emit(Shuffle.EventType.REMOVED, {\n        type: Shuffle.EventType.REMOVED,\n        shuffle: this,\n        collection,\n      });\n    };\n\n    // Hide collection first.\n    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 to look for.\n   * @return A shuffle item or undefined if it's not found.\n   */\n  getItemByElement(element: HTMLElement): ShuffleItem | undefined {\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(): void {\n    // Remove refs to current items.\n    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    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(): void {\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    disposeItems(this.items);\n\n    this.items.length = 0;\n    this.sortedItems.length = 0;\n\n    // Null DOM references\n    this.sizer = null;\n    // @ts-expect-error instead of creating a complicated union type for when\n    // a shuffle instance is destroyed, just ignore it.\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  static getSize: typeof getSize = getSize;\n  static ShuffleItem: typeof ShuffleItem = ShuffleItem;\n  static ALL_ITEMS: string = ALL_ITEMS;\n  static FILTER_ATTRIBUTE_KEY: string = FILTER_ATTRIBUTE_KEY;\n  static EventType: typeof EventType = EventType;\n  static Classes: typeof Classes = Classes;\n  static FilterMode: typeof FilterMode = FilterMode;\n  static options: typeof DEFAULT_OPTIONS = DEFAULT_OPTIONS;\n  static Point: typeof Point = Point;\n  static Rect: typeof Rect = Rect;\n}\n\nexport default Shuffle;\n"],"mappings":";;;;AAKA,IAAa,cAAb,MAAyB;CACvB;CAEA,GAAG,OAAe,UAAoB,KAAiB;EACrD,MAAM,WAAW,KAAK,aAAa,KAAK,WAAW,EAAE;AAErD,GAAC,SAAS,WAAW,SAAS,SAAS,EAAE,GAAG,KAAK;GAC/C,IAAI;GACJ;GACD,CAAC;AAEF,SAAO;;CAGT,KAAK,OAAe,UAAoB,KAAiB;EAEvD,MAAM,OAAO;EACb,SAAS,WAAW;AAClB,QAAK,IAAI,OAAO,SAAS;AAEzB,YAAS,MAAM,KAAK,UAAU;;AAGhC,WAAS,SAAS;AAClB,SAAO,KAAK,GAAG,OAAO,UAAU,IAAI;;CAGtC,KAAK,OAAe,GAAG,MAAmB;EACxC,MAAM,OAAO;EACb,MAAM,SAAS,CAAC,IAAK,KAAK,aAAa,KAAK,WAAW,EAAE,GAAG,UAAU,EAAE,CAAE;EAC1E,IAAI,IAAI;EACR,MAAM,MAAM,OAAO;AAEnB,SAAQ,IAAI,KAAK,KAAK,EACpB,QAAO,GAAG,GAAG,MAAM,OAAO,GAAG,KAAK,KAAK;AAGzC,SAAO;;CAGT,IAAI,OAAe,UAA2B;EAC5C,MAAM,WAAW,KAAK,aAAa,KAAK,WAAW,EAAE;EACrD,MAAM,OAAO,SAAS;EACtB,MAAM,aAAa,EAAE;AAErB,MAAI,QAAQ,UACV;QAAK,IAAI,IAAI,GAAG,MAAM,KAAK,QAAQ,IAAI,KAAK,KAAK,EAC/C,KAAI,KAAK,GAAG,OAAO,YAAY,KAAK,GAAG,GAAG,WAAW,SACnD,YAAW,KAAK,KAAK,GAAG;;AAS9B,MAAI,WAAW,SAAS,EACtB,UAAS,SAAS;MAGlB,QAAO,SAAS;AAGlB,SAAO;;;;;;;;;;;AC7DX,SAAgB,SACd,KACA,SACA,UACM;AACN,KAAI,CAAC,SACH,KAAI,OAAO,YAAY,YAAY;AACjC,aAAW;AACX,YAAU;OAEV,YAAW;CAIf,IAAI,UAAU,OAAO,IAAI;AAEzB,KAAI,CAAC,SAAS;AACZ,WAAS,MAAM,EAAE,CAAC;AAClB;;CAGF,IAAI,WAAW;CAEf,MAAM,UAAU,IAAI,MAAM,QAAQ;AAElC,MAAK,IAAI,IAAI,GAAG,MAAM,IAAI,QAAQ,IAAI,KAAK,IAEzC,CADW,IAAI,GACZ,KAAK,SAAS,UAAU,EAAE,CAAC;CAGhC,SAAS,UAAU,GAAW;AAC5B,SAAO,SAAS,YAAY,KAAmB,QAAqB;AAClE,OAAI,SACF;AAGF,OAAI,KAAK;AACP,aAAU,KAAK,QAAQ;AACvB,eAAW;AACX;;AAGF,WAAQ,KAAK;AAEb,OAAI,CAAC,EAAE,QACL,UAAU,MAAM,QAAQ;;;;AAMhC,SAAS,OAAa;;;;;;;;;ACpDtB,SAAgB,gBAAgB,UAAyB,UAA4B;CACnF,MAAM,OAAO;CAGb,MAAM,OAAO,SAAS,KAAK,YAAY;EACrC,MAAM,EAAE,UAAU;EAClB,MAAM,WAAW,MAAM;EACvB,MAAM,QAAQ,MAAM;AAGpB,QAAM,qBAAqB;AAC3B,QAAM,kBAAkB;AAExB,SAAO;GACL;GACA;GACD;GACD;AAEF,WAAU;AAIV,UAAS,GAAG;AAGZ,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GAAG;AAC3C,WAAS,GAAG,MAAM,qBAAqB,KAAK,GAAG;AAC/C,WAAS,GAAG,MAAM,kBAAkB,KAAK,GAAG;;;;;;;AAQhD,SAAgB,iBAAiB,SAA4B;AAC3D,KAAI,QAAQ,SAAS,EAGnB,iBAFiB,QAAQ,KAAK,QAAQ,IAAI,KAAK,QAAQ,QAEvB;AAC9B,OAAK,MAAM,OAAO,SAAS;AACzB,OAAI,KAAK,SAAS,IAAI,OAAO;AAC7B,OAAI,UAAU;;GAEhB;;AAIN,SAAgB,YAAkB,OAAuB;AACvD,QAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;;AAG5B,MAAM,iBAAiB;AACvB,IAAI,QAAwB;AAE5B,SAAgB,mBAA4B;AAC1C,KAAI,UAAU,KACZ,QAAO;CAGT,MAAM,UAAU,SAAS,QAAQ,SAAS;CAC1C,MAAM,MAAM,SAAS,cAAc,MAAM;AACzC,KAAI,MAAM,UAAU;AACpB,SAAQ,OAAO,IAAI;CAEnB,MAAM,EAAE,UAAU,WAAW,iBAAiB,KAAK,KAAK;AAExD,SAAQ,KAAK,MAAM,UAAU,MAAM,CAAC,KAAK;AAEzC,KAAI,QAAQ;AAEZ,QAAO;;AAGT,MAAM,iBAAiB;;;;;;AAQvB,SAAgB,UAAU,OAAwB;AAChD,QAAO,OAAO,WAAW,OAAO,MAAM,CAAC,IAAI;;;;;;;;;;;AAY7C,SAAgB,eACd,SACA,OACA,SAA8B,WAAW,iBAAiB,SAAS,KAAK,EAChE;CACR,IAAI,QAAQ,UAAU,OAAO,OAAO;AAGpC,KAAI,CAAC,kBAAkB,IAAI,UAAU,QACnC,UACE,UAAU,OAAO,YAAY,GAC7B,UAAU,OAAO,aAAa,GAC9B,UAAU,OAAO,gBAAgB,GACjC,UAAU,OAAO,iBAAiB;UAC3B,CAAC,kBAAkB,IAAI,UAAU,SAC1C,UACE,UAAU,OAAO,WAAW,GAC5B,UAAU,OAAO,cAAc,GAC/B,UAAU,OAAO,eAAe,GAChC,UAAU,OAAO,kBAAkB;AAGvC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;AAyBT,SAAgB,QAAQ,SAAsB,iBAAiB,OAA0C;CAEvG,MAAM,SAAS,WAAW,iBAAiB,SAAS,KAAK;CACzD,IAAI,QAAQ,eAAe,SAAS,SAAS,OAAO;CACpD,IAAI,SAAS,eAAe,SAAS,UAAU,OAAO;AAEtD,KAAI,gBAAgB;EAClB,MAAM,aAAa,eAAe,SAAS,cAAc,OAAO;EAChE,MAAM,cAAc,eAAe,SAAS,eAAe,OAAO;EAClE,MAAM,YAAY,eAAe,SAAS,aAAa,OAAO;EAC9D,MAAM,eAAe,eAAe,SAAS,gBAAgB,OAAO;AACpE,WAAS,aAAa;AACtB,YAAU,YAAY;;AAGxB,QAAO;EACL;EACA;EACD;;;;;ACtKH,IAAa,QAAb,MAAmB;CACjB;CACA;;;;;;CAOA,YAAY,GAAqB,GAAqB;AACpD,OAAK,IAAI,UAAU,EAAE;AACrB,OAAK,IAAI,UAAU,EAAE;;;;;;;;CASvB,OAAO,OAAO,QAAe,QAAwB;AACnD,SAAO,OAAO,MAAM,OAAO,KAAK,OAAO,MAAM,OAAO;;;;;;ACvBxD,IAAa,OAAb,MAAkB;CAChB;CACA;CACA;CACA;CACA;;;;;;;;;;CAWA,YAAY,GAAW,GAAW,OAAe,QAAgB,IAAY;AAC3E,OAAK,KAAK;AACV,OAAK,OAAO;AACZ,OAAK,MAAM;AACX,OAAK,QAAQ;AACb,OAAK,SAAS;;;;;;;;CAShB,OAAO,WAAW,OAAa,OAAsB;AACnD,SACE,MAAM,OAAO,MAAM,OAAO,MAAM,SAChC,MAAM,OAAO,MAAM,OAAO,MAAM,SAChC,MAAM,MAAM,MAAM,MAAM,MAAM,UAC9B,MAAM,MAAM,MAAM,MAAM,MAAM;;;;;;ACjCpC,MAAa,UAAU;CACrB,MAAM;CACN,cAAc;CACd,SAAS;CACT,QAAQ;CACT;AAED,MAAa,YAAY;AAEzB,MAAa,uBAAuB;AAEpC,MAAa,aAGT;CACF,KAAK;CACL,KAAK;CACN;AAED,MAAa,YAGT;CACF,QAAQ;CACR,SAAS;CACV;AAED,MAAa,kBAAkC;CAE7C,OAAO;CAGP,OAAO;CAGP,QAAQ;CAGR,cAAc;CAId,OAAO;CAIP,aAAa;CAIb,aAAa;CAIb,WAAW;CAIX,QAAQ;CAIR,iBAAiB;CAIjB,aAAa;CAGb,eAAe;CAGf,kBAAkB;CAGlB,eAAe;CAMf,YAAY,WAAW;CAGvB,YAAY;CAGZ,OAAO;CAIP,iBAAiB;CAClB;;;;AC1FD,IAAIA,OAAK;AAET,IAAa,cAAb,MAAa,YAAY;CACvB;CACA;CACA;CACA;CACA;CACA,QAAQ;CACR,QAAe,IAAI,OAAO;CAE1B,YAAY,SAAsB,OAAiB;AACjD,UAAM;AACN,OAAK,KAAKA;AACV,OAAK,UAAU;;;;AAKf,OAAK,QAAQ,QAAQ,MAAM;;;;AAK3B,OAAK,YAAY;;;;;;;AAQjB,OAAK,WAAW;;CAGlB,OAAa;AACX,OAAK,YAAY;AACjB,OAAK,QAAQ,UAAU,OAAO,QAAQ,OAAO;AAC7C,OAAK,QAAQ,UAAU,IAAI,QAAQ,QAAQ;AAC3C,OAAK,QAAQ,gBAAgB,cAAc;;CAG7C,OAAa;AACX,OAAK,YAAY;AACjB,OAAK,QAAQ,UAAU,OAAO,QAAQ,QAAQ;AAC9C,OAAK,QAAQ,UAAU,IAAI,QAAQ,OAAO;AAC1C,OAAK,QAAQ,aAAa,eAAe,OAAO;;CAGlD,OAAa;AACX,OAAK,WAAW,CAAC,QAAQ,cAAc,QAAQ,QAAQ,CAAC;AACxD,OAAK,SAAS,YAAY,IAAI,QAAQ;AACtC,OAAK,SAAS,KAAK,QAAQ,YAAY,IAAI,UAAU,MAAM,YAAY,IAAI,UAAU,IAAI;AACzF,OAAK,QAAQ,YAAY,MAAM;AAC/B,OAAK,QAAQ,IAAI,OAAO;;CAG1B,WAAW,SAAyB;AAClC,OAAK,MAAM,aAAa,QACtB,MAAK,QAAQ,UAAU,IAAI,UAAU;;CAIzC,cAAc,SAAyB;AACrC,OAAK,MAAM,aAAa,QACtB,MAAK,QAAQ,UAAU,OAAO,UAAU;;CAI5C,SAAS,KAA4B;AACnC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAE5C,MAAK,QAAQ,MAAM,OAAO,OAAO,MAAM;;CAI3C,UAAgB;AACd,OAAK,cAAc;GAAC,QAAQ;GAAQ,QAAQ;GAAS,QAAQ;GAAa,CAAC;AAE3E,OAAK,QAAQ,gBAAgB,QAAQ;AAErC,OAAK,UAAU;;CAGjB,OAAO,MAAsB;EAC3B,SAAS;GACP,UAAU;GACV,KAAK;GACL,YAAY;GACZ,YAAY;GACb;EACD,WAAW;GACT,KAAK,EACH,MAAM,GACP;GACD,KAAK,EACH,OAAO,GACR;GACF;EACD,SAAS;GACP,QAAQ;IACN,SAAS;IACT,YAAY;IACb;GACD,OAAO,EACL,iBAAiB,IAClB;GACF;EACD,QAAQ;GACN,QAAQ,EACN,SAAS,GACV;GACD,OAAO;IACL,YAAY;IACZ,iBAAiB;IAClB;GACF;EACF;CAED,OAAO,QAAQ;EACb,SAAS;EACT,QAAQ;EACT;;;;;;AAOH,SAAgB,oBAAoB,EAAE,SAAS,UAA2B;AACxE,MAAK,MAAM,QAAQ,QACjB,MAAK,MAAM;AAGb,MAAK,MAAM,QAAQ,OACjB,MAAK,MAAM;;;;;;AAQf,SAAgB,UAAU,OAA4B;AACpD,MAAK,MAAM,QAAQ,MACjB,MAAK,MAAM;;;;;;AAQf,SAAgB,aAAa,OAA4B;AACvD,MAAK,MAAM,QAAQ,MACjB,MAAK,SAAS;;AAIlB,SAAgB,iBAAiB,MAAyB;AACxD,MAAK,QAAQ,YAAY,MAAM;AAC/B,MAAK,WAAW;AAChB,MAAK,SAAS,YAAY,IAAI,OAAO,OAAO;AAC5C,MAAK,SAAS,YAAY,IAAI,OAAO,MAAM;;;;;;;;;;;;AC7J7C,SAAS,UAAgB,OAAuB;CAC9C,IAAI,QAAQ,MAAM;AAElB,QAAO,OAAO;AACZ,WAAS;EACT,MAAM,QAAQ,KAAK,MAAM,KAAK,QAAQ,IAAI,QAAQ,GAAG;EACrD,MAAM,OAAO,MAAM;AACnB,QAAM,SAAS,MAAM;AACrB,QAAM,SAAS;;AAGjB,QAAO;;AAGT,MAAM,WAAW;CAEf,SAAS;CAGT,IAAI;CAGJ,SAAS;CAGT,WAAW;CAIX,KAAK;CACN;;;;;;;AAQD,SAAgB,OAAO,KAAoB,SAA6C;AAEtF,KAAI,CAAC,MAAM,QAAQ,IAAI,CACrB,QAAO,EAAE;CAGX,MAAM,OAAO;EAAE,GAAG;EAAU,GAAG;EAAS;CACxC,MAAM,WAAW,CAAC,GAAG,IAAI;CACzB,IAAI,SAAS;AAEb,KAAI,IAAI,WAAW,EACjB,QAAO,EAAE;AAGX,KAAI,KAAK,UACP,QAAO,UAAU,IAAI;AAKvB,KAAI,OAAO,KAAK,OAAO,YAAY;EACjC,MAAM,SAAS,KAAK;AACpB,MAAI,MAAM,OAAO,UAAU;AAEzB,OAAI,OACF,QAAO;GAGT,MAAM,aAAa,MAAM,KAAK;GAC9B,MAAM,aAAa,MAAM,KAAK;GAG9B,MAAM,OAAO,OAAO,WAAW;GAG/B,MAAM,OAAO,OAAO,WAAW;AAG/B,OAAI,SAAS,UAAa,SAAS,QAAW;AAC5C,aAAS;AACT,WAAO;;AAGT,OAAI,OAAO,QAAQ,SAAS,eAAe,SAAS,WAClD,QAAO;AAGT,OAAI,OAAO,QAAQ,SAAS,cAAc,SAAS,YACjD,QAAO;AAGT,UAAO;IACP;YACO,OAAO,KAAK,YAAY,WACjC,KAAI,KAAK,KAAK,QAAQ;AAIxB,KAAI,OACF,QAAO;AAGT,KAAI,KAAK,QACP,KAAI,SAAS;AAGf,QAAO;;;;;AC3GT,IAAa,oBAAb,MAA+B;CAC7B,+BAAe,IAAI,KAAyB;CAC5C,SAAS;CAET,YAAoB;AAClB,QAAKC,SAAU;AACf,SAAO,gBAAgB,MAAKA;;CAG9B,kBAAkB,SAAsB,UAA2C;EACjF,MAAM,KAAK,MAAKC,UAAW;EAC3B,MAAM,YAAY,UAA2B;AAC3C,OAAI,MAAM,kBAAkB,MAAM,QAAQ;AACxC,SAAK,iBAAiB,GAAG;AACzB,aAAS,MAAM;;;AAInB,UAAQ,iBAAiB,iBAAiB,SAA0B;AACpE,QAAKC,YAAa,IAAI,IAAI;GAAE;GAAS;GAAU,CAAC;AAEhD,SAAO;;CAGT,iBAAiB,IAAqB;EACpC,MAAM,QAAQ,MAAKA,YAAa,IAAI,GAAG;AACvC,MAAI,OAAO;AACT,SAAM,QAAQ,oBAAoB,iBAAiB,MAAM,SAA0B;AACnF,SAAKA,YAAa,OAAO,GAAG;AAC5B,UAAO;;AAGT,SAAO;;CAGT,YAAkB;AAChB,OAAK,MAAM,MAAM,MAAKA,YAAa,MAAM,CACvC,MAAK,iBAAiB,GAAG;;;AAK/B,SAAgB,0BAA6C;AAC3D,QAAO,IAAI,mBAAmB;;;;;;;;;;;;;ACvChC,SAAgB,cAAc,WAAmB,aAAqB,SAAiB,WAA2B;CAChH,IAAI,aAAa,YAAY;AAK7B,KAAI,KAAK,IAAI,KAAK,MAAM,WAAW,GAAG,WAAW,GAAG,UAElD,cAAa,KAAK,MAAM,WAAW;AAIrC,QAAO,KAAK,IAAI,KAAK,KAAK,WAAW,EAAE,QAAQ;;;;;;;;;AAUjD,SAAgB,sBAAsB,WAAqB,YAAoB,SAA2B;AAExG,KAAI,eAAe,EACjB,QAAO;CAyBT,MAAM,YAAY,EAAE;AAGpB,MAAK,IAAI,IAAI,GAAG,KAAK,UAAU,YAAY,KAAK,EAE9C,WAAU,KAAK,KAAK,IAAI,GAAG,UAAU,MAAM,GAAG,IAAI,WAAW,CAAC,CAAC;AAGjE,QAAO;;;;;;;;;AAUT,SAAgB,eAAe,WAAqB,QAAwB;CAC1E,MAAM,cAAc,KAAK,IAAI,GAAG,UAAU;AAC1C,MAAK,IAAI,IAAI,GAAG,MAAM,UAAU,QAAQ,IAAI,KAAK,KAAK,EACpD,KAAI,UAAU,MAAM,cAAc,UAAU,UAAU,MAAM,cAAc,OACxE,QAAO;AAIX,QAAO;;;;;;;AAuBT,SAAgB,gBAAgB,EAC9B,UACA,WACA,UACA,OACA,WACA,UAC4B;CAC5B,MAAM,OAAO,cAAc,SAAS,OAAO,UAAU,OAAO,UAAU;CACtE,MAAM,OAAO,sBAAsB,WAAW,MAAM,MAAM;CAC1D,MAAM,mBAAmB,eAAe,MAAM,OAAO;CAGrD,MAAM,QAAQ,IAAI,MAAM,WAAW,kBAAkB,KAAK,kBAAkB;CAK5E,MAAM,YAAY,KAAK,oBAAoB,SAAS;AACpD,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK,EAC7B,WAAU,mBAAmB,KAAK;AAGpC,QAAO;;;;;;;;;;AAWT,SAAgB,qBAAqB,WAAmB,gBAAiC;CACvF,MAAM,SAAiC,EAAE;AAKzC,MAAK,MAAM,YAAY,UACrB,KAAI,OAAO,SAAS,SAAS,OAE3B,QAAO,SAAS,OAAO,CAAC,SAAS;KAGjC,QAAO,SAAS,KAAK,KAAK,SAAS;CAOvC,MAAM,QAAgB,EAAE;CACxB,MAAM,OAAiB,EAAE;CACzB,MAAM,eAAyB,EAAE;AACjC,MAAK,MAAM,aAAa,OAAO,OAAO,OAAO,EAAE;AAC7C,OAAK,KAAK,UAAU;EACpB,MAAM,WAAW,UAAU,GAAG,GAAG;EACjC,MAAM,MAAM,SAAS,OAAO,SAAS;EACrC,MAAM,SAAS,KAAK,OAAO,iBAAiB,OAAO,EAAE;EAErD,IAAI,aAAa;EACjB,IAAI,UAAU;AACd,MAAI,SAAS,GAAG;GACd,MAAM,WAAmB,EAAE;AAC3B,aAAU,UAAU,OAAO,mBAAmB;IAC5C,MAAM,UAAU,IAAI,KAClB,eAAe,OAAO,QACtB,eAAe,KACf,eAAe,OACf,eAAe,QACf,eAAe,GAChB;IAGD,MAAM,YAAY,CAAC,MAAM,MAAM,cAAc,KAAK,WAAW,SAAS,UAAU,CAAC;AAEjF,aAAS,KAAK,QAAQ;AACtB,WAAO;KACP;AAGF,OAAI,QACF,cAAa;;AAOjB,MAAI,CAAC,SAAS;GACZ,IAAI;AAYJ,OAXmB,UAAU,MAAM,aACjC,MAAM,MAAM,mBAAmB;IAC7B,MAAM,aAAa,KAAK,WAAW,UAAU,eAAe;AAC5D,QAAI,WACF,oBAAmB;AAErB,WAAO;KACP,CACH,EAGe;IACd,MAAM,WAAW,aAAa,WAAW,UAAU,MAAM,SAAS,iBAAiB,CAAC;AACpF,iBAAa,OAAO,UAAU,GAAG,KAAK,UAAU;;;AAIpD,QAAM,KAAK,GAAG,WAAW;AACzB,eAAa,KAAK,WAAW;;AAO/B,QAAO,aACJ,MAAM,CACN,UAAU,MAAM,SAAS,KAAK,KAAK,KAAK,GAAG,CAC3C,KAAK,aAAa,IAAI,MAAM,SAAS,MAAM,SAAS,IAAI,CAAC;;;;;AClM9D,IAAI,KAAK;AAET,IAAM,UAAN,MAAM,gBAAgB,YAAY;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,kBAAyC;;;;;;;;CASzC,YAAY,SAAwB,UAAmC,EAAE,EAAE;AACzE,SAAO;AACP,OAAK,UAAU;GAAE,GAAG,QAAQ;GAAS,GAAG;GAAS;AAEjD,OAAK,WAAW,EAAE;AAClB,OAAK,QAAQ,QAAQ;AACrB,OAAK,aAAa,QAAQ;AAC1B,OAAK,YAAY;AACjB,OAAK,cAAc;AACnB,OAAK,gBAAgB;AACrB,QAAKC,oBAAqB,yBAAyB;AACnD,OAAK,kBAAkB;AACvB,QAAKC,QAAS,EAAE;EAEhB,MAAM,KAAK,MAAKC,iBAAkB,QAAQ;AAE1C,MAAI,CAAC,GACH,OAAM,IAAI,UAAU,mDAAmD;AAGzE,OAAK,UAAU;AACf,OAAK,KAAK,WAAW;AACrB,QAAM;AAEN,OAAK,QAAQ,MAAKC,UAAW;AAC7B,OAAK,cAAc,KAAK;AAExB,OAAK,QAAQ,MAAKD,iBAAkB,KAAK,QAAQ,MAAM;AAGvD,OAAK,QAAQ,UAAU,IAAI,QAAQ,QAAQ,KAAK;AAGhD,YAAU,KAAK,MAAM;AAKrB,MAAI,SAAS,eAAe,YAAY;GACtC,MAAM,SAAS,KAAK,OAAO,KAAK,KAAK;AACrC,UAAO,iBAAiB,QAAQ,SAAS,SAAS;AAChD,WAAO,oBAAoB,QAAQ,OAAO;AAC1C,YAAQ;KACR;;EAIJ,MAAM,eAAe,WAAW,iBAAiB,KAAK,SAAS,KAAK;EACpE,MAAM,iBAAiB,QAAQ,QAAQ,KAAK,QAAQ,CAAC;AAGrD,QAAKE,eAAgB,aAAa;AAIlC,QAAKC,WAAY,eAAe;AAGhC,OAAK,OAAO,KAAK,QAAQ,OAAO,KAAK,QAAQ,YAAY;AAGzD,QAAKC,QAAS;AACd,QAAKC,iBAAkB,IAAI,eAAe,MAAKC,qBAAsB,KAAK,KAAK,CAAC;AAChF,QAAKD,eAAgB,QAAQ,KAAK,QAAQ;AAO1C,OAAK,QAAQ;AACb,OAAK,mBAAmB,KAAK,MAAM;AACnC,OAAK,QAAQ,MAAM,aAAa,UAAU,KAAK,QAAQ,MAAM,KAAK,KAAK,QAAQ;AAC/E,OAAK,gBAAgB;;CAavB,GAAG,OAAe,UAAgC,SAAqB;AACrE,SAAO,MAAM,GAAG,OAAO,UAAU,QAAQ;;CAY3C,KAAK,OAAe,UAAgC,SAAqB;AACvE,SAAO,MAAM,KAAK,OAAO,UAAU,QAAQ;;CAI7C,KAA8C,OAAkB,MAAwC;AACtG,MAAI,KAAK,YACP,QAAO;AAET,SAAO,MAAM,KAAK,OAAO,KAAK;;CAGhC,IAAI,OAAe,UAAuC;AACxD,SAAO,MAAM,IAAI,OAAO,SAAS;;;;;;;CAQnC,kBAAkB,QAAmD;AAGnE,MAAI,OAAO,WAAW,SACpB,QAAO,KAAK,UAAU,KAAK,QAAQ,cAAc,OAAO,GAAG,SAAS,cAAc,OAAO;AAI3F,MAAI,UAAU,cAAc,UAAU,OAAO,YAAY,OAAO,aAAa,EAC3E,QAAO;AAIT,MAAI,UAAU,YAAY,OACxB,QAAO,OAAO;AAGhB,SAAO;;;;;;CAOT,gBAAgB,QAAmC;AAEjD,MAAI,OAAO,aAAa,SACtB,MAAK,QAAQ,MAAM,WAAW;AAIhC,MAAI,OAAO,aAAa,SACtB,MAAK,QAAQ,MAAM,WAAW;;;;;;;;CAUlC,QAAQ,WAAsB,KAAK,YAAY,aAA4B,KAAK,OAAkB;EAChG,MAAM,MAAM,MAAKE,gBAAiB,UAAU,WAAW;AAGvD,sBAAoB,IAAI;AAGxB,OAAK,aAAa;AAIlB,MAAI,OAAO,aAAa,SACtB,MAAK,QAAQ;AAGf,SAAO;;;;;;;CAQT,iBAAiB,UAAqB,OAAiC;EACrE,IAAI,UAAyB,EAAE;EAC/B,MAAM,SAAwB,EAAE;AAGhC,MAAI,aAAa,QAAQ,UACvB,WAAU;MAKV,MAAK,MAAM,QAAQ,MACjB,KAAI,MAAKC,eAAgB,UAAU,KAAK,QAAQ,CAC9C,SAAQ,KAAK,KAAK;MAElB,QAAO,KAAK,KAAK;AAKvB,SAAO;GACL;GACA;GACD;;;;;;;;CASH,gBAAgB,UAAqB,SAA+B;AAClE,MAAI,OAAO,aAAa,WACtB,QAAO,SAAS,KAAK,SAAS,SAAS,KAAK;EAI9C,MAAM,OAAO,QAAQ,QAAQ,QAAQ,yBAAyB;EAC9D,MAAM,OAAO,KAAK,QAAQ,YAAY,KAAK,MAAM,KAAK,QAAQ,UAAU,GAAI,KAAK,MAAM,KAAK;EAE5F,SAAS,aAAa,UAA2B;AAC/C,UAAO,KAAK,SAAS,SAAS;;AAGhC,MAAI,MAAM,QAAQ,SAAS,EAAE;AAC3B,OAAI,KAAK,QAAQ,eAAe,WAAW,IACzC,QAAO,SAAS,KAAK,aAAa;AAEpC,UAAO,SAAS,MAAM,aAAa;;AAGrC,SAAO,KAAK,SAAS,SAAS;;;;;CAMhC,mBAAyB;AACvB,OAAK,eAAe,MAAKC,kBAAmB,CAAC;;;;;;;;;CAU/C,mBAAmB,OAA4B;EAC7C,MAAM,EAAE,OAAO,WAAW,KAAK;EAC/B,MAAM,gBAAgB,KAAK,QAAQ,gBAAgB,CAAC,YAAY,GAAG,CAAC,OAAO,OAAO;EAIlF,MAAM,WAAW,OAAO,KAAK,YAAY,IAAI,OAAO,OAAO;EAC3D,MAAM,aAAa,CAAC,GAAG,eAAe,GAAG,SAAS,CAAC,KAAK,IAAI;AAE5D,OAAK,MAAM,QAAQ,OAAO;AACxB,QAAK,QAAQ,MAAM,qBAAqB,GAAG,MAAM;AAGjD,QAAK,QAAQ,MAAM,2BAA2B;AAC9C,QAAK,QAAQ,MAAM,qBAAqB;;;CAI5C,YAA2B;AACzB,SAEE,MAAM,KAAK,KAAK,QAAQ,SAAS,CAC9B,QAAQ,OAAO,GAAG,QAAQ,KAAK,QAAQ,aAAc,CAAC,CACtD,KAAK,OAAO,IAAI,YAAY,IAAmB,KAAK,QAAQ,MAAM,CAAC;;;;;;CAQ1E,eAAe,OAAqC;EAElD,MAAM,WAAW,MAAM,KAAK,KAAK,QAAQ,SAAS;AAClD,SAAO,OAAO,CAAC,GAAG,KAAK,OAAO,GAAG,MAAM,EAAE,EACvC,GAAG,SAAS;AACV,UAAO,SAAS,QAAQ,QAAQ;KAEnC,CAAC;;CAGJ,oBAAmC;AACjC,SAAO,KAAK,MAAM,QAAQ,SAAS,KAAK,UAAU;;CAGpD,qBAAoC;AAClC,SAAO,KAAK,MAAM,QAAQ,SAAS,CAAC,KAAK,UAAU;;;;;;;CAQrD,eAAe,gBAAwB,YAA4B;EACjE,IAAI;AAGJ,MAAI,OAAO,KAAK,QAAQ,gBAAgB,WACtC,QAAO,KAAK,QAAQ,YAAY,eAAe;WAGtC,KAAK,MACd,QAAO,QAAQ,QAAQ,KAAK,MAAM,CAAC;WAG1B,KAAK,QAAQ,YACtB,QAAO,KAAK,QAAQ;WAGX,KAAK,MAAM,SAAS,EAC7B,QAAO,QAAQ,QAAQ,KAAK,MAAM,GAAG,SAAS,KAAK,CAAC;MAIpD,QAAO;AAIT,MAAI,SAAS,EACX,QAAO;AAGT,SAAO,OAAO;;;;;;CAOhB,eAAe,gBAAgC;AAC7C,MAAI,OAAO,KAAK,QAAQ,gBAAgB,WACtC,QAAO,KAAK,QAAQ,YAAY,eAAe;AAGjD,MAAI,KAAK,MACP,QAAO,eAAe,KAAK,OAAO,aAAa;AAGjD,MAAI,KAAK,QAAQ,YACf,QAAO,KAAK,QAAQ;AAGtB,SAAO;;;;;;CAOT,YAAY,iBAAyB,QAAQ,QAAQ,KAAK,QAAQ,CAAC,OAAa;EAC9E,MAAM,SAAS,MAAKC,cAAe,eAAe;EAClD,MAAM,cAAc,MAAKC,cAAe,gBAAgB,OAAO;EAC/D,IAAI,qBAAqB,iBAAiB,UAAU;EAGpD,MAAM,YAAY,KAAK,QAAQ;AAG/B,MAAI,KAAK,IAAI,KAAK,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,UAEhE,qBAAoB,KAAK,MAAM,kBAAkB;AAGnD,OAAK,OAAO,KAAK,IAAI,KAAK,MAAM,qBAAqB,EAAE,EAAE,EAAE;AAC3D,OAAK,iBAAiB;AACtB,OAAK,WAAW;;;;;CAMlB,oBAA0B;AACxB,OAAK,QAAQ,MAAM,SAAS,GAAG,MAAKC,kBAAmB,CAAC;;;;;CAM1D,oBAA4B;AAC1B,SAAO,KAAK,IAAI,GAAG,KAAK,UAAU;;;;;;CAOpC,kBAAkB,OAAuB;AACvC,SAAO,KAAK,IAAI,QAAQ,KAAK,QAAQ,eAAgB,KAAK,QAAQ,iBAAkB;;;;;CAMtF,aAAmB;EACjB,IAAI,IAAI,KAAK;AACb,OAAK,YAAY,EAAE;AACnB,SAAO,GAAG;AACR,QAAK;AACL,QAAK,UAAU,KAAK,EAAE;;;;;;;CAQ1B,QAAQ,OAA4B;EAClC,MAAM,gBAAgB,MAAKC,iBAAkB,MAAM;EAEnD,IAAI,QAAQ;AACZ,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxC,MAAM,OAAO,MAAM;GACnB,MAAM,iBAAiB;AACrB,SAAK,SAAS,YAAY,IAAI,QAAQ,MAAM;;AAK9C,OAAI,MAAM,OAAO,KAAK,OAAO,cAAc,GAAG,IAAI,CAAC,KAAK,UAAU;AAChE,SAAK,SAAS,YAAY,IAAI,QAAQ,OAAO;AAC7C,cAAU;AACV;;AAGF,QAAK,QAAQ,cAAc;AAC3B,QAAK,QAAQ,YAAY,MAAM;AAC/B,QAAK,WAAW;GAIhB,MAAM,SAAS,KAAK,uBAAuB,MAAM,YAAY,IAAI,QAAQ,OAAO;AAChF,UAAO,kBAAkB,GAAG,MAAKC,iBAAkB,MAAM,CAAC;AAE1D,SAAKf,MAAO,KAAK;IACf;IACA;IACA;IACD,CAAC;AAEF,YAAS;;;;;;;;CASb,kBAAkB,OAA+B;AAG/C,MAAI,KAAK,QAAQ,YAAY;GAC3B,MAAM,YAAY,MAAM,KAAK,MAAM,MAAM;IACvC,MAAM,WAAW,QAAQ,QAAQ,KAAK,SAAS,KAAK;IACpD,MAAM,QAAQ,MAAKgB,gBAAiB,SAAS;AAC7C,WAAO,IAAI,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,OAAO,SAAS,QAAQ,EAAE;KACrE;AAEF,UAAO,KAAK,wBAAwB,WAAW,KAAK,eAAe;;AAKrE,SAAO,MAAM,KAAK,SAAS,MAAKA,gBAAiB,QAAQ,QAAQ,KAAK,SAAS,KAAK,CAAC,CAAC;;;;;;CAOxF,iBAAiB,UAAoD;AACnE,SAAO,gBAAgB;GACrB;GACA,WAAW,KAAK;GAChB,UAAU,KAAK;GACf,OAAO,KAAK;GACZ,WAAW,KAAK,QAAQ;GACxB,QAAQ,KAAK,QAAQ;GACtB,CAAC;;;;;;;;CASJ,wBAAwB,WAAmB,gBAAiC;AAC1E,SAAO,qBAAqB,WAAW,eAAe;;;;;;CAOxD,QAAQ,aAA4B,MAAKC,mBAAoB,EAAQ;EACnE,IAAI,QAAQ;AACZ,OAAK,MAAM,QAAQ,YAAY;GAC7B,MAAM,iBAAiB;AACrB,SAAK,SAAS,YAAY,IAAI,OAAO,MAAM;;AAS7C,OAAI,KAAK,UAAU;AACjB,SAAK,SAAS,YAAY,IAAI,OAAO,OAAO;AAC5C,cAAU;AACV;;AAGF,QAAK,QAAQ,YAAY,MAAM;AAC/B,QAAK,WAAW;GAEhB,MAAM,SAAS,KAAK,uBAAuB,MAAM,YAAY,IAAI,OAAO,OAAO;AAC/E,UAAO,kBAAkB,GAAG,MAAKF,iBAAkB,MAAM,CAAC;AAE1D,SAAKf,MAAO,KAAK;IACf;IACA;IACA;IACD,CAAC;AAEF,YAAS;;;;;;;CAQb,sBAAsB,SAAsC;AAG1D,MAAI,CAAC,KAAK,aAAa,KAAK,YAC1B;AAGF,OAAK,MAAM,SAAS,QAClB,KAAI,KAAK,MAAM,MAAM,YAAY,MAAM,KAAK,KAAK,MAAM,KAAK,eAAe,EAAE;AAE3E,wBAAqB,MAAKK,MAAQ;AAElC,SAAKA,QAAS,4BAA4B;AACxC,SAAK,QAAQ;KACb;;;;;;;;;CAWR,AAAU,uBAAuB,MAAmB,aAA+C;EAEjG,MAAM,SAAS,EAAE,GAAG,aAAa;AAEjC,MAAI,KAAK,QAAQ,cAIf,QAAO,YAAY,aAHN,KAAK,QAAQ,QAAQ,MAAM,KAC9B,KAAK,QAAQ,kBAAkB,KAAK,MAAM,KAAK,MAAM,EAAE,GAAG,KAAK,MAAM,EAEtC,MAD/B,KAAK,QAAQ,kBAAkB,KAAK,MAAM,KAAK,MAAM,EAAE,GAAG,KAAK,MAAM,EAC9B,YAAY,KAAK,MAAM;OACnE;AACL,OAAI,KAAK,QAAQ,MACf,QAAO,QAAQ,GAAG,KAAK,MAAM,EAAE;OAE/B,QAAO,OAAO,GAAG,KAAK,MAAM,EAAE;AAEhC,UAAO,MAAM,GAAG,KAAK,MAAM,EAAE;;AAG/B,SAAO;;;;;;;;;CAUT,oBACE,SACA,cACA,MACM;AACN,QAAKN,kBAAmB,kBAAkB,UAAU,QAAQ;AAC1D,iBAAc;AACd,QAAK,MAAM,IAAI;IACf;;;;;;;CAQJ,uBAAuB,MAA4E;AACjG,UAAQ,SAAS;AACf,QAAK,KAAK,SAAS,KAAK,OAAO;AAC/B,SAAKmB,mBAAoB,KAAK,KAAK,SAAS,KAAK,UAAU,KAAK;;;;;;;CAQpE,gBAAsB;AACpB,MAAI,KAAK,gBACP,OAAKC,gBAAiB;EAGxB,MAAM,WAAW,OAAO,KAAK,QAAQ,UAAU,YAAY,KAAK,QAAQ,QAAQ;EAChF,MAAM,WAAW,MAAKnB,MAAO,SAAS;AAEtC,MAAI,YAAY,YAAY,KAAK,cAC/B,OAAKoB,iBAAkB,MAAKpB,MAAO;WAC1B,UAAU;AACnB,oBAAiB,MAAKA,MAAO;AAC7B,QAAK,KAAK,QAAQ,UAAU,QAAQ;IAClC,MAAM,QAAQ,UAAU;IACxB,SAAS;IACV,CAAC;QAMF,MAAK,KAAK,QAAQ,UAAU,QAAQ;GAClC,MAAM,QAAQ,UAAU;GACxB,SAAS;GACV,CAAC;AAIJ,QAAKA,MAAO,SAAS;;;;;;CAOvB,kBAAkB,aAAgC;AAEhD,OAAK,kBAAkB;AAKvB,WAFkB,YAAY,KAAK,QAAQ,MAAKqB,sBAAuB,IAAI,CAAC,EAExD,MAAKC,iBAAkB,KAAK,KAAK,CAAC;;CAGxD,kBAAwB;AAEtB,QAAKvB,kBAAmB,WAAW;AAGnC,OAAK,kBAAkB;;CAGzB,oBAA0B;AACxB,OAAK,kBAAkB;AACvB,OAAK,KAAK,QAAQ,UAAU,QAAQ;GAClC,MAAM,QAAQ,UAAU;GACxB,SAAS;GACV,CAAC;;;;;;;CAQJ,OAAO,UAAsB,aAAwC;AACnE,MAAI,CAAC,KAAK,UACR;AAGF,MAAI,CAAC,YAAY,SAAS,WAAW,EAEnC,YAAW,QAAQ;AAGrB,QAAKwB,OAAQ,SAAS;AAGtB,QAAKC,QAAS;AAGd,QAAKC,iBAAkB;AAGvB,OAAK,KAAK,YAAY;;;;;;CAOxB,KAAK,cAAkC,KAAK,UAAgB;AAC1D,MAAI,CAAC,KAAK,UACR;AAGF,QAAKC,WAAY;EAEjB,MAAM,QAAQ,OAAO,MAAKhB,kBAAmB,EAAE,YAAY;AAC3D,OAAK,cAAc;AAEnB,QAAKiB,OAAQ,MAAM;AAInB,QAAKC,cAAe;AAGpB,QAAKC,kBAAmB;AAExB,OAAK,WAAW;;;;;;;;;CAUlB,OAAO,EACL,mBAAmB,MACnB,QAAQ,UAIN,EAAE,EAAQ;AACZ,MAAI,KAAK,aAAa,OAAO;AAC3B,OAAI,iBACF,OAAKzB,YAAa;AAIpB,QAAK,MAAM;;;;;;;;CASf,SAAe;AACb,OAAK,OAAO,EACV,kBAAkB,MACnB,CAAC;;;;;;;CAQJ,IAAI,UAA+B;EACjC,MAAM,QAAQ,YAAY,SAAS,CAAC,KAAK,OAAO,IAAI,YAAY,IAAI,KAAK,QAAQ,MAAM,CAAC;AAGxF,YAAU,MAAM;AAGhB,QAAKsB,WAAY;EAGjB,MAAM,cAAc,OADH,MAAKI,cAAe,MAAM,EACN,KAAK,SAAS;EACnD,MAAM,oBAAoB,MAAKP,OAAQ,KAAK,YAAY,YAAY;EAIpE,MAAM,gBAAgB,MAAKT,iBAAkB,kBAAkB,QAAQ;AACvE,OAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,QAAQ,QAAQ,KAAK,GAAG;GAC5D,MAAM,OAAO,kBAAkB,QAAQ;AACvC,OAAI,MAAM,SAAS,KAAK,EAAE;AACxB,SAAK,QAAQ,cAAc;AAC3B,qBAAiB,KAAK;AACtB,SAAK,SAAS,KAAK,uBAAuB,MAAM,EAAE,CAAC,CAAC;;;AAIxD,OAAK,MAAM,QAAQ,kBAAkB,OACnC,KAAI,MAAM,SAAS,KAAK,CACtB,kBAAiB,KAAK;AAM1B,OAAK,QAAQ;AAGb,OAAK,mBAAmB,MAAM;AAG9B,OAAK,QAAQ,MAAKgB,cAAe,MAAM;AAGvC,OAAK,OAAO,KAAK,WAAW;;;;;CAM9B,UAAgB;AACd,OAAK,YAAY;;;;;;CAOnB,OAAO,iBAAiB,MAAY;AAClC,OAAK,YAAY;AACjB,MAAI,eACF,MAAK,QAAQ;;;;;;CAQjB,OAAO,UAA+B;AACpC,MAAI,SAAS,WAAW,EACtB;EAGF,MAAM,aAAa,YAAY,SAAS;EAExC,MAAM,WAAW,WAAW,KAAK,YAAY,KAAK,iBAAiB,QAAQ,CAAC,CAAC,OAAO,QAAQ;EAE5F,MAAM,qBAAqB;AACzB,gBAAa,SAAS;AAGtB,QAAK,MAAM,WAAW,WACpB,SAAQ,QAAQ;AAGlB,QAAK,KAAK,QAAQ,UAAU,SAAS;IACnC,MAAM,QAAQ,UAAU;IACxB,SAAS;IACT;IACD,CAAC;;AAIJ,sBAAoB;GAClB,SAAS,EAAE;GACX,QAAQ;GACT,CAAC;AAEF,QAAKN,OAAQ,SAAS;AAEtB,OAAK,MAAM;AAIX,OAAK,QAAQ,KAAK,MAAM,QAAQ,SAAS,CAAC,SAAS,SAAS,KAAK,CAAC;AAClE,QAAKC,iBAAkB;AAEvB,OAAK,KAAK,QAAQ,UAAU,QAAQ,aAAa;;;;;;;CAQnD,iBAAiB,SAA+C;AAC9D,SAAO,KAAK,MAAM,MAAM,SAAS,KAAK,YAAY,QAAQ;;;;;;CAO5D,aAAmB;AAEjB,eAAa,KAAK,MAAM;AACxB,OAAK,gBAAgB;AAGrB,OAAK,QAAQ,MAAKvB,UAAW;AAG7B,YAAU,KAAK,MAAM;AAErB,OAAK,KAAK,QAAQ,UAAU,cAAc;AAExC,QAAK,mBAAmB,KAAK,MAAM;AACnC,QAAK,gBAAgB;IACrB;AAGF,OAAK,OAAO,KAAK,WAAW;;;;;CAM9B,UAAgB;AACd,QAAKiB,gBAAiB;AACtB,MAAI,MAAKb,gBAAiB;AACxB,SAAKA,eAAgB,UAAU,KAAK,QAAQ;AAC5C,SAAKA,iBAAkB;;AAIzB,OAAK,QAAQ,UAAU,OAAO,UAAU;AACxC,OAAK,QAAQ,gBAAgB,QAAQ;AAGrC,eAAa,KAAK,MAAM;AAExB,OAAK,MAAM,SAAS;AACpB,OAAK,YAAY,SAAS;AAG1B,OAAK,QAAQ;AAGb,OAAK,UAAU;AAIf,OAAK,cAAc;AACnB,OAAK,YAAY;;CAGnB,OAAO,UAA0B;CACjC,OAAO,cAAkC;CACzC,OAAO,YAAoB;CAC3B,OAAO,uBAA+B;CACtC,OAAO,YAA8B;CACrC,OAAO,UAA0B;CACjC,OAAO,aAAgC;CACvC,OAAO,UAAkC;CACzC,OAAO,QAAsB;CAC7B,OAAO,OAAoB"}