ngx-drag-to-select
Version: 
A lightweight, fast, configurable and reactive drag-to-select component for Angular 8 and beyond
1 lines • 70.5 kB
Source Map (JSON)
{"version":3,"file":"ngx-drag-to-select.mjs","sources":["../../../projects/ngx-drag-to-select/src/lib/config.ts","../../../projects/ngx-drag-to-select/src/lib/constants.ts","../../../projects/ngx-drag-to-select/src/lib/utils.ts","../../../projects/ngx-drag-to-select/src/lib/operators.ts","../../../projects/ngx-drag-to-select/src/lib/keyboard-events.service.ts","../../../projects/ngx-drag-to-select/src/lib/tokens.ts","../../../projects/ngx-drag-to-select/src/lib/select-item.directive.ts","../../../projects/ngx-drag-to-select/src/lib/models.ts","../../../projects/ngx-drag-to-select/src/lib/shortcut.service.ts","../../../projects/ngx-drag-to-select/src/lib/select-container.component.ts","../../../projects/ngx-drag-to-select/src/lib/drag-to-select.module.ts","../../../projects/ngx-drag-to-select/src/public_api.ts","../../../projects/ngx-drag-to-select/src/ngx-drag-to-select.ts"],"sourcesContent":["import { DragToSelectConfig } from './models';\n\nexport const DEFAULT_CONFIG: DragToSelectConfig = {\n  selectedClass: 'selected',\n  shortcuts: {\n    moveRangeStart: 'shift+r',\n    disableSelection: 'alt',\n    toggleSingleItem: 'meta',\n    addToSelection: 'shift',\n    removeFromSelection: 'shift+meta',\n  },\n};\n","export const AUDIT_TIME = 16;\nexport const MIN_WIDTH = 5;\nexport const MIN_HEIGHT = 5;\nexport const NO_SELECT_CLASS = 'dts-no-select';\n","import { MIN_HEIGHT, MIN_WIDTH } from './constants';\nimport { BoundingBox, MousePosition, SelectBox, SelectContainerHost } from './models';\n\nexport const isObject = (item: any) => {\n  return item && typeof item === 'object' && !Array.isArray(item) && item !== null;\n};\n\nexport function mergeDeep(target: Record<string, any>, source: Record<string, any>) {\n  if (isObject(target) && isObject(source)) {\n    Object.keys(source).forEach((key) => {\n      if (isObject(source[key])) {\n        if (!target[key]) {\n          Object.assign(target, { [key]: {} });\n        }\n        mergeDeep(target[key], source[key]);\n      } else {\n        Object.assign(target, { [key]: source[key] });\n      }\n    });\n  }\n\n  return target;\n}\n\nexport const hasMinimumSize = (selectBox: SelectBox<number>, minWidth = MIN_WIDTH, minHeight = MIN_HEIGHT) => {\n  return selectBox.width > minWidth || selectBox.height > minHeight;\n};\n\nexport const clearSelection = (window: Window) => {\n  const selection = window.getSelection();\n\n  if (!selection) {\n    return;\n  }\n\n  if (selection.removeAllRanges) {\n    selection.removeAllRanges();\n  } else if (selection.empty) {\n    selection.empty();\n  }\n};\n\nexport const inBoundingBox = (point: MousePosition, box: BoundingBox) => {\n  return (\n    box.left <= point.x && point.x <= box.left + box.width && box.top <= point.y && point.y <= box.top + box.height\n  );\n};\n\nexport const boxIntersects = (boxA: BoundingBox, boxB: BoundingBox) => {\n  return (\n    boxA.left <= boxB.left + boxB.width &&\n    boxA.left + boxA.width >= boxB.left &&\n    boxA.top <= boxB.top + boxB.height &&\n    boxA.top + boxA.height >= boxB.top\n  );\n};\n\nexport const calculateBoundingClientRect = (element: HTMLElement): BoundingBox => {\n  return element.getBoundingClientRect();\n};\n\nexport const getMousePosition = (event: MouseEvent) => {\n  return {\n    x: event.clientX,\n    y: event.clientY,\n  };\n};\n\nexport const getScroll = () => {\n  if (!document || !document.documentElement) {\n    return {\n      x: 0,\n      y: 0,\n    };\n  }\n\n  return {\n    x: document.documentElement.scrollLeft || document.body.scrollLeft,\n    y: document.documentElement.scrollTop || document.body.scrollTop,\n  };\n};\n\nexport const getRelativeMousePosition = (event: MouseEvent, container: SelectContainerHost): MousePosition => {\n  const { x: clientX, y: clientY } = getMousePosition(event);\n  const scroll = getScroll();\n\n  const borderSize = (container.boundingClientRect.width - container.clientWidth) / 2;\n  const offsetLeft = container.boundingClientRect.left + scroll.x;\n  const offsetTop = container.boundingClientRect.top + scroll.y;\n\n  return {\n    x: clientX - borderSize - (offsetLeft - window.pageXOffset) + container.scrollLeft,\n    y: clientY - borderSize - (offsetTop - window.pageYOffset) + container.scrollTop,\n  };\n};\n\nexport const cursorWithinElement = (event: MouseEvent, element: HTMLElement) => {\n  const mousePoint = getMousePosition(event);\n  return inBoundingBox(mousePoint, calculateBoundingClientRect(element));\n};\n","import { Observable } from 'rxjs';\nimport { distinctUntilChanged, filter, map, withLatestFrom } from 'rxjs/operators';\nimport { MousePosition, SelectBox, SelectBoxInput, SelectContainerHost } from './models';\nimport { getRelativeMousePosition, hasMinimumSize } from './utils';\n\nexport const createSelectBox = (container: SelectContainerHost) => {\n  return (source: Observable<SelectBoxInput>): Observable<SelectBox<number>> => {\n    return source.pipe(\n      map(([event, opacity, { x, y }]) => {\n        // Type annotation is required here, because `getRelativeMousePosition` returns a `MousePosition`,\n        // the TS compiler cannot figure out the shape of this type.\n        const mousePosition: MousePosition = getRelativeMousePosition(event, container);\n\n        const width = opacity > 0 ? mousePosition.x - x : 0;\n        const height = opacity > 0 ? mousePosition.y - y : 0;\n\n        return {\n          top: height < 0 ? mousePosition.y : y,\n          left: width < 0 ? mousePosition.x : x,\n          width: Math.abs(width),\n          height: Math.abs(height),\n          opacity,\n        };\n      })\n    );\n  };\n};\n\nexport const whenSelectBoxVisible = (selectBox$: Observable<SelectBox<number>>) => (source: Observable<Event>) =>\n  source.pipe(\n    withLatestFrom(selectBox$),\n    filter(([, selectBox]) => hasMinimumSize(selectBox, 0, 0)),\n    map(([event, _]) => event)\n  );\n\nexport const distinctKeyEvents = () => (source: Observable<KeyboardEvent>) =>\n  source.pipe(\n    distinctUntilChanged((prev, curr) => {\n      return prev && curr && prev.code === curr.code;\n    })\n  );\n","import { isPlatformBrowser } from '@angular/common';\nimport { Inject, Injectable, PLATFORM_ID } from '@angular/core';\nimport { fromEvent, Observable } from 'rxjs';\nimport { share } from 'rxjs/operators';\nimport { distinctKeyEvents } from './operators';\n\n@Injectable()\nexport class KeyboardEventsService {\n  keydown$: Observable<KeyboardEvent>;\n  keyup$: Observable<KeyboardEvent>;\n  distinctKeydown$: Observable<KeyboardEvent>;\n  distinctKeyup$: Observable<KeyboardEvent>;\n  mouseup$: Observable<MouseEvent>;\n  mousemove$: Observable<MouseEvent>;\n\n  constructor(@Inject(PLATFORM_ID) private platformId: Record<string, unknown>) {\n    if (isPlatformBrowser(this.platformId)) {\n      this._initializeKeyboardStreams();\n    }\n  }\n\n  private _initializeKeyboardStreams() {\n    this.keydown$ = fromEvent<KeyboardEvent>(window, 'keydown').pipe(share());\n    this.keyup$ = fromEvent<KeyboardEvent>(window, 'keyup').pipe(share());\n\n    // distinctKeyEvents is used to prevent multiple key events to be fired repeatedly\n    // on Windows when a key is being pressed\n\n    this.distinctKeydown$ = this.keydown$.pipe(distinctKeyEvents(), share());\n\n    this.distinctKeyup$ = this.keyup$.pipe(distinctKeyEvents(), share());\n\n    this.mouseup$ = fromEvent<MouseEvent>(window, 'mouseup').pipe(share());\n    this.mousemove$ = fromEvent<MouseEvent>(window, 'mousemove').pipe(share());\n  }\n}\n","import { InjectionToken } from '@angular/core';\nimport { DragToSelectConfig } from './models';\n\nexport const CONFIG = new InjectionToken<DragToSelectConfig>('DRAG_TO_SELECT_CONFIG');\nexport const USER_CONFIG = new InjectionToken<DragToSelectConfig>('USER_CONFIG');\n","import { isPlatformBrowser } from '@angular/common';\n\nimport {\n  Directive,\n  DoCheck,\n  ElementRef,\n  Inject,\n  Input,\n  PLATFORM_ID,\n  Renderer2,\n  OnInit,\n  HostBinding,\n} from '@angular/core';\n\nimport { DragToSelectConfig, BoundingBox } from './models';\nimport { CONFIG } from './tokens';\nimport { calculateBoundingClientRect } from './utils';\n\nexport const SELECT_ITEM_INSTANCE = Symbol();\n\n@Directive({\n  selector: '[dtsSelectItem]',\n  exportAs: 'dtsSelectItem',\n})\nexport class SelectItemDirective implements OnInit, DoCheck {\n  private _boundingClientRect: BoundingBox | undefined;\n\n  selected = false;\n\n  @HostBinding('class.dts-range-start')\n  rangeStart = false;\n\n  @HostBinding('class.dts-select-item')\n  readonly hostClass = true;\n\n  @Input() dtsSelectItem: any | undefined;\n\n  @Input()\n  @HostBinding('class.dts-disabled')\n  dtsDisabled = false;\n\n  get value(): SelectItemDirective | any {\n    return this.dtsSelectItem ? this.dtsSelectItem : this;\n  }\n\n  constructor(\n    @Inject(CONFIG) private config: DragToSelectConfig,\n    @Inject(PLATFORM_ID) private platformId: Record<string, unknown>,\n    private host: ElementRef,\n    private renderer: Renderer2\n  ) {}\n\n  ngOnInit() {\n    this.nativeElememnt[SELECT_ITEM_INSTANCE] = this;\n  }\n\n  ngDoCheck() {\n    this.applySelectedClass();\n  }\n\n  toggleRangeStart() {\n    this.rangeStart = !this.rangeStart;\n  }\n\n  get nativeElememnt() {\n    return this.host.nativeElement;\n  }\n\n  getBoundingClientRect() {\n    if (isPlatformBrowser(this.platformId) && !this._boundingClientRect) {\n      this.calculateBoundingClientRect();\n    }\n    return this._boundingClientRect;\n  }\n\n  calculateBoundingClientRect() {\n    const boundingBox = calculateBoundingClientRect(this.host.nativeElement);\n    this._boundingClientRect = boundingBox;\n    return boundingBox;\n  }\n\n  _select() {\n    this.selected = true;\n  }\n\n  _deselect() {\n    this.selected = false;\n  }\n\n  private applySelectedClass() {\n    if (this.selected) {\n      this.renderer.addClass(this.host.nativeElement, this.config.selectedClass);\n    } else {\n      this.renderer.removeClass(this.host.nativeElement, this.config.selectedClass);\n    }\n  }\n}\n","import { Observable } from 'rxjs';\nimport { SelectItemDirective } from './select-item.directive';\n\nexport type PredicateFn<T> = (item: T) => boolean;\n\nexport enum UpdateActions {\n  Add,\n  Remove,\n}\n\nexport interface UpdateAction {\n  type: UpdateActions;\n  item: SelectItemDirective;\n}\n\nexport interface ObservableProxy<T> {\n  proxy$: Observable<any>;\n  proxy: T;\n}\n\nexport interface SelectContainerHost extends HTMLElement {\n  boundingClientRect: BoundingBox;\n}\n\nexport interface Shortcuts {\n  moveRangeStart: string;\n  disableSelection: string;\n  toggleSingleItem: string;\n  addToSelection: string;\n  removeFromSelection: string;\n}\n\nexport interface DragToSelectConfig {\n  selectedClass: string;\n  shortcuts: Partial<Shortcuts>;\n}\n\nexport interface MousePosition {\n  x: number;\n  y: number;\n}\n\nexport interface BoundingBox {\n  top: number;\n  left: number;\n  width: number;\n  height: number;\n}\n\nexport type SelectBoxInput = [MouseEvent, number, MousePosition];\n\nexport interface SelectBox<T> {\n  top: T;\n  left: T;\n  width: T;\n  height: T;\n  opacity: number;\n}\n\nexport enum Action {\n  Add,\n  Delete,\n  None,\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport { Inject, Injectable, PLATFORM_ID } from '@angular/core';\nimport { merge } from 'rxjs';\nimport { distinctUntilChanged, map } from 'rxjs/operators';\nimport { KeyboardEventsService } from './keyboard-events.service';\nimport { DragToSelectConfig } from './models';\nimport { CONFIG } from './tokens';\n\nconst SUPPORTED_META_KEYS = {\n  alt: true,\n  shift: true,\n  meta: true,\n  ctrl: true,\n};\n\nconst SUPPORTED_KEYS = /[a-z]/;\n\nconst META_KEY = 'meta';\n\nconst KEY_ALIASES = {\n  [META_KEY]: ['ctrl', 'meta'],\n};\n\nconst SUPPORTED_SHORTCUTS = {\n  moveRangeStart: true,\n  disableSelection: true,\n  toggleSingleItem: true,\n  addToSelection: true,\n  removeFromSelection: true,\n};\n\nconst ERROR_PREFIX = '[ShortcutService]';\n\ninterface KeyState {\n  code: string;\n  pressed: boolean;\n}\n\n@Injectable()\nexport class ShortcutService {\n  private _shortcuts: { [key: string]: string[][] } = {};\n\n  private _latestShortcut: Map<string, boolean> = new Map();\n\n  constructor(\n    @Inject(PLATFORM_ID) private platformId: Record<string, unknown>,\n    @Inject(CONFIG) config: DragToSelectConfig,\n    private keyboardEvents: KeyboardEventsService\n  ) {\n    this._shortcuts = this._createShortcutsFromConfig(config.shortcuts);\n\n    if (isPlatformBrowser(this.platformId)) {\n      const keydown$ = this.keyboardEvents.keydown$.pipe(\n        map<KeyboardEvent, KeyState>((event) => ({ code: event.code, pressed: true }))\n      );\n\n      const keyup$ = this.keyboardEvents.keyup$.pipe(\n        map<KeyboardEvent, KeyState>((event) => ({ code: event.code, pressed: false }))\n      );\n\n      merge<KeyState>(keydown$, keyup$)\n        .pipe(\n          distinctUntilChanged((prev, curr) => {\n            return prev.pressed === curr.pressed && prev.code === curr.code;\n          })\n        )\n        .subscribe((keyState) => {\n          if (keyState.pressed) {\n            this._latestShortcut.set(keyState.code, true);\n          } else {\n            this._latestShortcut.delete(keyState.code);\n          }\n        });\n    }\n  }\n\n  disableSelection(event: Event) {\n    return this._isShortcutPressed('disableSelection', event);\n  }\n\n  moveRangeStart(event: Event) {\n    return this._isShortcutPressed('moveRangeStart', event);\n  }\n\n  toggleSingleItem(event: Event) {\n    return this._isShortcutPressed('toggleSingleItem', event);\n  }\n\n  addToSelection(event: Event) {\n    return this._isShortcutPressed('addToSelection', event);\n  }\n\n  removeFromSelection(event: Event) {\n    return this._isShortcutPressed('removeFromSelection', event);\n  }\n\n  extendedSelectionShortcut(event: Event) {\n    return this.addToSelection(event) || this.removeFromSelection(event);\n  }\n\n  private _createShortcutsFromConfig(shortcuts: { [key: string]: string }) {\n    const shortcutMap = {};\n\n    for (const [key, shortcutsForCommand] of Object.entries(shortcuts)) {\n      if (!this._isSupportedShortcut(key)) {\n        throw new Error(this._getErrorMessage(`Shortcut ${key} not supported`));\n      }\n\n      shortcutsForCommand\n        .replace(/ /g, '')\n        .split(',')\n        .forEach((shortcut) => {\n          if (!shortcutMap[key]) {\n            shortcutMap[key] = [];\n          }\n\n          const combo = shortcut.split('+');\n          const cleanCombos = this._substituteKey(shortcut, combo, META_KEY);\n\n          cleanCombos.forEach((cleanCombo) => {\n            const unsupportedKey = this._isSupportedCombo(cleanCombo);\n\n            if (unsupportedKey) {\n              throw new Error(this._getErrorMessage(`Key '${unsupportedKey}' in shortcut ${shortcut} not supported`));\n            }\n\n            shortcutMap[key].push(\n              cleanCombo.map((comboKey) => {\n                return SUPPORTED_META_KEYS[comboKey] ? `${comboKey}Key` : `Key${comboKey.toUpperCase()}`;\n              })\n            );\n          });\n        });\n    }\n\n    return shortcutMap;\n  }\n\n  private _substituteKey(shortcut: string, combo: Array<string>, substituteKey: string) {\n    const hasSpecialKey = shortcut.includes(substituteKey);\n    const substitutedShortcut: string[][] = [];\n\n    if (hasSpecialKey) {\n      const cleanShortcut = combo.filter((element) => element !== META_KEY);\n\n      KEY_ALIASES.meta.forEach((alias) => {\n        substitutedShortcut.push([...cleanShortcut, alias]);\n      });\n    } else {\n      substitutedShortcut.push(combo);\n    }\n\n    return substitutedShortcut;\n  }\n\n  private _getErrorMessage(message: string) {\n    return `${ERROR_PREFIX} ${message}`;\n  }\n\n  private _isShortcutPressed(shortcutName: string, event: Event) {\n    const shortcuts = this._shortcuts[shortcutName];\n\n    return shortcuts.some((shortcut) => {\n      return shortcut.every((key) => this._isKeyPressed(event, key));\n    });\n  }\n\n  private _isKeyPressed(event: Event, key: string) {\n    return key.startsWith('Key') ? this._latestShortcut.has(key) : event[key];\n  }\n\n  private _isSupportedCombo(combo: Array<string>) {\n    let unsupportedKey = null;\n\n    combo.forEach((key) => {\n      if (!SUPPORTED_META_KEYS[key] && (!SUPPORTED_KEYS.test(key) || this._isSingleChar(key))) {\n        unsupportedKey = key;\n        return;\n      }\n    });\n\n    return unsupportedKey;\n  }\n\n  private _isSingleChar(key: string) {\n    return key.length > 1;\n  }\n\n  private _isSupportedShortcut(shortcut: string) {\n    return SUPPORTED_SHORTCUTS[shortcut];\n  }\n}\n","import {\n  Component,\n  ElementRef,\n  Output,\n  EventEmitter,\n  Input,\n  OnDestroy,\n  Renderer2,\n  ViewChild,\n  NgZone,\n  ContentChildren,\n  QueryList,\n  HostBinding,\n  AfterViewInit,\n  PLATFORM_ID,\n  Inject,\n  AfterContentInit,\n} from '@angular/core';\n\nimport { isPlatformBrowser } from '@angular/common';\n\nimport { Observable, Subject, combineLatest, merge, from, fromEvent, BehaviorSubject, asyncScheduler } from 'rxjs';\n\nimport {\n  switchMap,\n  takeUntil,\n  map,\n  tap,\n  filter,\n  auditTime,\n  mapTo,\n  share,\n  withLatestFrom,\n  distinctUntilChanged,\n  observeOn,\n  startWith,\n  concatMapTo,\n  first,\n} from 'rxjs/operators';\n\nimport { SelectItemDirective, SELECT_ITEM_INSTANCE } from './select-item.directive';\nimport { ShortcutService } from './shortcut.service';\n\nimport { createSelectBox, whenSelectBoxVisible, distinctKeyEvents } from './operators';\n\nimport {\n  Action,\n  SelectBox,\n  MousePosition,\n  SelectContainerHost,\n  UpdateAction,\n  UpdateActions,\n  PredicateFn,\n  BoundingBox,\n} from './models';\n\nimport { AUDIT_TIME, NO_SELECT_CLASS } from './constants';\n\nimport {\n  inBoundingBox,\n  cursorWithinElement,\n  clearSelection,\n  boxIntersects,\n  calculateBoundingClientRect,\n  getRelativeMousePosition,\n  getMousePosition,\n  hasMinimumSize,\n} from './utils';\nimport { KeyboardEventsService } from './keyboard-events.service';\n\n@Component({\n  selector: 'dts-select-container',\n  exportAs: 'dts-select-container',\n  template: `\n    <ng-content></ng-content>\n    <div\n      class=\"dts-select-box\"\n      #selectBox\n      [ngClass]=\"selectBoxClasses$ | async\"\n      [ngStyle]=\"selectBoxStyles$ | async\"\n    ></div>\n  `,\n  styleUrls: ['./select-container.component.scss'],\n})\nexport class SelectContainerComponent implements AfterViewInit, OnDestroy, AfterContentInit {\n  host: SelectContainerHost;\n  selectBoxStyles$: Observable<SelectBox<string>>;\n  selectBoxClasses$: Observable<{ [key: string]: boolean }>;\n\n  @ViewChild('selectBox', { static: true })\n  private $selectBox: ElementRef;\n\n  @ContentChildren(SelectItemDirective, { descendants: true })\n  private $selectableItems: QueryList<SelectItemDirective>;\n\n  @Input() selectedItems: any;\n  @Input() selectOnDrag = true;\n  @Input() disabled = false;\n  @Input() disableDrag = false;\n  @Input() selectOnClick = true;\n  @Input() dragOverItems = true;\n  @Input() disableRangeSelection = false;\n  @Input() selectMode = false;\n  @Input() selectWithShortcut = false;\n\n  @Input()\n  @HostBinding('class.dts-custom')\n  custom = false;\n\n  @HostBinding('class.dts-select-container')\n  readonly hostClass = true;\n\n  @Output()\n  selectedItemsChange = new EventEmitter<any>();\n  @Output() select = new EventEmitter<any>();\n  @Output() itemSelected = new EventEmitter<any>();\n  @Output() itemDeselected = new EventEmitter<any>();\n  @Output() selectionStarted = new EventEmitter<void>();\n  @Output() selectionEnded = new EventEmitter<Array<any>>();\n\n  private _tmpItems = new Map<SelectItemDirective, Action>();\n\n  private _selectedItems$ = new BehaviorSubject<Array<any>>([]);\n  private _selectableItems: Array<SelectItemDirective> = [];\n  private updateItems$ = new Subject<UpdateAction>();\n  private destroy$ = new Subject<void>();\n\n  private _lastRange: [number, number] = [-1, -1];\n  private _lastStartIndex: number | undefined = undefined;\n  private _newRangeStart = false;\n  private _lastRangeSelection: Map<SelectItemDirective, boolean> = new Map();\n\n  constructor(\n    @Inject(PLATFORM_ID) private platformId: Record<string, unknown>,\n    private shortcuts: ShortcutService,\n    private keyboardEvents: KeyboardEventsService,\n    private hostElementRef: ElementRef,\n    private renderer: Renderer2,\n    private ngZone: NgZone\n  ) {}\n\n  ngAfterViewInit() {\n    if (isPlatformBrowser(this.platformId)) {\n      this.host = this.hostElementRef.nativeElement;\n\n      this._initSelectedItemsChange();\n\n      this._calculateBoundingClientRect();\n      this._observeBoundingRectChanges();\n      this._observeSelectableItems();\n\n      const mouseup$ = this.keyboardEvents.mouseup$.pipe(\n        filter(() => !this.disabled),\n        tap(() => this._onMouseUp()),\n        share()\n      );\n\n      const mousemove$ = this.keyboardEvents.mousemove$.pipe(\n        filter(() => !this.disabled),\n        share()\n      );\n\n      const mousedown$ = fromEvent<MouseEvent>(this.host, 'mousedown').pipe(\n        filter((event) => event.button === 0), // only emit left mouse\n        filter(() => !this.disabled),\n        filter((event) => this.selectOnClick || event.target === this.host),\n        tap((event) => this._onMouseDown(event)),\n        share()\n      );\n\n      const dragging$ = mousedown$.pipe(\n        filter((event) => !this.shortcuts.disableSelection(event)),\n        filter(() => !this.selectMode),\n        filter(() => !this.disableDrag),\n        filter((event) => this.dragOverItems || event.target === this.host),\n        switchMap(() => mousemove$.pipe(takeUntil(mouseup$))),\n        share()\n      );\n\n      const currentMousePosition$: Observable<MousePosition> = mousedown$.pipe(\n        map((event: MouseEvent) => getRelativeMousePosition(event, this.host))\n      );\n\n      const show$ = dragging$.pipe(mapTo(1));\n      const hide$ = mouseup$.pipe(mapTo(0));\n      const opacity$ = merge(show$, hide$).pipe(distinctUntilChanged());\n\n      const selectBox$ = combineLatest([dragging$, opacity$, currentMousePosition$]).pipe(\n        createSelectBox(this.host),\n        share()\n      );\n\n      this.selectBoxClasses$ = merge(\n        dragging$,\n        mouseup$,\n        this.keyboardEvents.distinctKeydown$,\n        this.keyboardEvents.distinctKeyup$\n      ).pipe(\n        auditTime(AUDIT_TIME),\n        withLatestFrom(selectBox$),\n        map(([event, selectBox]) => {\n          return {\n            'dts-adding': hasMinimumSize(selectBox, 0, 0) && !this.shortcuts.removeFromSelection(event),\n            'dts-removing': this.shortcuts.removeFromSelection(event),\n          };\n        }),\n        distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))\n      );\n\n      const selectOnMouseUp$ = dragging$.pipe(\n        filter(() => !this.selectOnDrag),\n        filter(() => !this.selectMode),\n        filter((event) => this._cursorWithinHost(event)),\n        switchMap((_) => mouseup$.pipe(first())),\n        filter(\n          (event) =>\n            (!this.shortcuts.disableSelection(event) && !this.shortcuts.toggleSingleItem(event)) ||\n            this.shortcuts.removeFromSelection(event)\n        )\n      );\n\n      const selectOnDrag$ = selectBox$.pipe(\n        auditTime(AUDIT_TIME),\n        withLatestFrom(mousemove$, (selectBox, event: MouseEvent) => ({\n          selectBox,\n          event,\n        })),\n        filter(() => this.selectOnDrag),\n        filter(({ selectBox }) => hasMinimumSize(selectBox)),\n        map(({ event }) => event)\n      );\n\n      const selectOnKeyboardEvent$ = merge(\n        this.keyboardEvents.distinctKeydown$,\n        this.keyboardEvents.distinctKeyup$\n      ).pipe(\n        auditTime(AUDIT_TIME),\n        whenSelectBoxVisible(selectBox$),\n        tap((event) => {\n          if (this._isExtendedSelection(event)) {\n            this._tmpItems.clear();\n          } else {\n            this._flushItems();\n          }\n        })\n      );\n\n      merge(selectOnMouseUp$, selectOnDrag$, selectOnKeyboardEvent$)\n        .pipe(takeUntil(this.destroy$))\n        .subscribe((event) => this._selectItems(event));\n\n      this.selectBoxStyles$ = selectBox$.pipe(\n        map((selectBox) => ({\n          top: `${selectBox.top}px`,\n          left: `${selectBox.left}px`,\n          width: `${selectBox.width}px`,\n          height: `${selectBox.height}px`,\n          opacity: selectBox.opacity,\n        }))\n      );\n\n      this._initSelectionOutputs(mousedown$, mouseup$);\n    }\n  }\n\n  ngAfterContentInit() {\n    this._selectableItems = this.$selectableItems.toArray();\n  }\n\n  selectAll() {\n    this.$selectableItems.forEach((item) => {\n      this._selectItem(item);\n    });\n  }\n\n  toggleItems<T>(predicate: PredicateFn<T>) {\n    this._filterSelectableItems(predicate).subscribe((item: SelectItemDirective) => this._toggleItem(item));\n  }\n\n  selectItems<T>(predicate: PredicateFn<T>) {\n    this._filterSelectableItems(predicate).subscribe((item: SelectItemDirective) => this._selectItem(item));\n  }\n\n  deselectItems<T>(predicate: PredicateFn<T>) {\n    this._filterSelectableItems(predicate).subscribe((item: SelectItemDirective) => this._deselectItem(item));\n  }\n\n  clearSelection() {\n    this.$selectableItems.forEach((item) => {\n      this._deselectItem(item);\n    });\n  }\n\n  update() {\n    this._calculateBoundingClientRect();\n    this.$selectableItems.forEach((item) => item.calculateBoundingClientRect());\n  }\n\n  ngOnDestroy() {\n    this.destroy$.next();\n    this.destroy$.complete();\n  }\n\n  private _filterSelectableItems<T>(predicate: PredicateFn<T>) {\n    // Wrap select items in an observable for better efficiency as\n    // no intermediate arrays are created and we only need to process\n    // every item once.\n    return from(this._selectableItems).pipe(filter((item) => predicate(item.value)));\n  }\n\n  private _initSelectedItemsChange() {\n    this._selectedItems$.pipe(auditTime(AUDIT_TIME), takeUntil(this.destroy$)).subscribe({\n      next: (selectedItems) => {\n        this.selectedItemsChange.emit(selectedItems);\n        this.select.emit(selectedItems);\n      },\n      complete: () => {\n        this.selectedItemsChange.emit([]);\n      },\n    });\n  }\n\n  private _observeSelectableItems() {\n    // Listen for updates and either select or deselect an item\n    this.updateItems$\n      .pipe(\n        withLatestFrom(this._selectedItems$),\n        takeUntil(this.destroy$),\n        filter(([update]) => !update.item.dtsDisabled)\n      )\n      .subscribe(([update, selectedItems]: [UpdateAction, any[]]) => {\n        const item = update.item;\n\n        switch (update.type) {\n          case UpdateActions.Add:\n            if (this._addItem(item, selectedItems)) {\n              item._select();\n            }\n            break;\n          case UpdateActions.Remove:\n            if (this._removeItem(item, selectedItems)) {\n              item._deselect();\n            }\n            break;\n        }\n      });\n\n    // Update the container as well as all selectable items if the list has changed\n    this.$selectableItems.changes\n      .pipe(withLatestFrom(this._selectedItems$), observeOn(asyncScheduler), takeUntil(this.destroy$))\n      .subscribe(([items, selectedItems]: [QueryList<SelectItemDirective>, any[]]) => {\n        const newList = items.toArray();\n        this._selectableItems = newList;\n        const newValues = newList.map((item) => item.value);\n        const removedItems = selectedItems.filter((item) => !newValues.includes(item));\n\n        if (removedItems.length) {\n          removedItems.forEach((item) => this._removeItem(item, selectedItems));\n        }\n\n        this.update();\n      });\n  }\n\n  private _observeBoundingRectChanges() {\n    this.ngZone.runOutsideAngular(() => {\n      const resize$ = fromEvent(window, 'resize');\n      const windowScroll$ = fromEvent(window, 'scroll');\n      const containerScroll$ = fromEvent(this.host, 'scroll');\n\n      merge(resize$, windowScroll$, containerScroll$)\n        .pipe(startWith('INITIAL_UPDATE'), auditTime(AUDIT_TIME), takeUntil(this.destroy$))\n        .subscribe(() => {\n          this.update();\n        });\n    });\n  }\n\n  private _initSelectionOutputs(mousedown$: Observable<MouseEvent>, mouseup$: Observable<MouseEvent>) {\n    mousedown$\n      .pipe(\n        filter((event) => this._cursorWithinHost(event)),\n        tap(() => this.selectionStarted.emit()),\n        concatMapTo(mouseup$.pipe(first())),\n        withLatestFrom(this._selectedItems$),\n        map(([, items]) => items),\n        takeUntil(this.destroy$)\n      )\n      .subscribe((items) => {\n        this.selectionEnded.emit(items);\n      });\n  }\n\n  private _calculateBoundingClientRect() {\n    this.host.boundingClientRect = calculateBoundingClientRect(this.host);\n  }\n\n  private _cursorWithinHost(event: MouseEvent) {\n    return cursorWithinElement(event, this.host);\n  }\n\n  private _onMouseUp() {\n    this._flushItems();\n    this.renderer.removeClass(document.body, NO_SELECT_CLASS);\n  }\n\n  private _onMouseDown(event: MouseEvent) {\n    if (this.shortcuts.disableSelection(event) || this.disabled) {\n      return;\n    }\n\n    clearSelection(window);\n\n    if (!this.disableDrag) {\n      this.renderer.addClass(document.body, NO_SELECT_CLASS);\n    }\n\n    if (this.shortcuts.removeFromSelection(event)) {\n      return;\n    }\n\n    const mousePoint = getMousePosition(event);\n    const [currentIndex, clickedItem] = this._getClosestSelectItem(event);\n\n    let [startIndex, endIndex] = this._lastRange;\n\n    const isMoveRangeStart = this.shortcuts.moveRangeStart(event);\n\n    const shouldResetRangeSelection =\n      !this.shortcuts.extendedSelectionShortcut(event) || isMoveRangeStart || this.disableRangeSelection;\n\n    if (shouldResetRangeSelection) {\n      this._resetRangeStart();\n    }\n\n    // move range start\n    if (shouldResetRangeSelection && !this.disableRangeSelection) {\n      if (currentIndex > -1) {\n        this._newRangeStart = true;\n        this._lastStartIndex = currentIndex;\n        clickedItem.toggleRangeStart();\n\n        this._lastRangeSelection.clear();\n      } else {\n        this._lastStartIndex = -1;\n      }\n    }\n\n    if (currentIndex > -1) {\n      startIndex = Math.min(this._lastStartIndex, currentIndex);\n      endIndex = Math.max(this._lastStartIndex, currentIndex);\n      this._lastRange = [startIndex, endIndex];\n    }\n\n    if (isMoveRangeStart) {\n      return;\n    }\n\n    this.$selectableItems.forEach((item, index) => {\n      const itemRect = item.getBoundingClientRect();\n      const withinBoundingBox = inBoundingBox(mousePoint, itemRect);\n\n      if (this.shortcuts.extendedSelectionShortcut(event) && this.disableRangeSelection) {\n        return;\n      }\n\n      const withinRange =\n        this.shortcuts.extendedSelectionShortcut(event) &&\n        startIndex > -1 &&\n        endIndex > -1 &&\n        index >= startIndex &&\n        index <= endIndex &&\n        startIndex !== endIndex;\n\n      const shouldAdd =\n        (withinBoundingBox &&\n          !this.shortcuts.toggleSingleItem(event) &&\n          !this.selectMode &&\n          !this.selectWithShortcut) ||\n        (this.shortcuts.extendedSelectionShortcut(event) && item.selected && !this._lastRangeSelection.get(item)) ||\n        withinRange ||\n        (withinBoundingBox && this.shortcuts.toggleSingleItem(event) && !item.selected) ||\n        (!withinBoundingBox && this.shortcuts.toggleSingleItem(event) && item.selected) ||\n        (withinBoundingBox && !item.selected && this.selectMode) ||\n        (!withinBoundingBox && item.selected && this.selectMode);\n\n      const shouldRemove =\n        (!withinBoundingBox &&\n          !this.shortcuts.toggleSingleItem(event) &&\n          !this.selectMode &&\n          !this.shortcuts.extendedSelectionShortcut(event) &&\n          !this.selectWithShortcut) ||\n        (this.shortcuts.extendedSelectionShortcut(event) && currentIndex > -1) ||\n        (!withinBoundingBox && this.shortcuts.toggleSingleItem(event) && !item.selected) ||\n        (withinBoundingBox && this.shortcuts.toggleSingleItem(event) && item.selected) ||\n        (!withinBoundingBox && !item.selected && this.selectMode) ||\n        (withinBoundingBox && item.selected && this.selectMode);\n\n      if (shouldAdd) {\n        this._selectItem(item);\n      } else if (shouldRemove) {\n        this._deselectItem(item);\n      }\n\n      if (withinRange && !this._lastRangeSelection.get(item)) {\n        this._lastRangeSelection.set(item, true);\n      } else if (!withinRange && !this._newRangeStart && !item.selected) {\n        this._lastRangeSelection.delete(item);\n      }\n    });\n\n    // if we don't toggle a single item, we set `newRangeStart` to `false`\n    // meaning that we are building up a range\n    if (!this.shortcuts.toggleSingleItem(event)) {\n      this._newRangeStart = false;\n    }\n  }\n\n  private _selectItems(event: Event) {\n    const selectionBox = calculateBoundingClientRect(this.$selectBox.nativeElement);\n\n    this.$selectableItems.forEach((item, index) => {\n      if (this._isExtendedSelection(event)) {\n        this._extendedSelectionMode(selectionBox, item, event);\n      } else {\n        this._normalSelectionMode(selectionBox, item, event);\n\n        if (this._lastStartIndex < 0 && item.selected) {\n          item.toggleRangeStart();\n          this._lastStartIndex = index;\n        }\n      }\n    });\n  }\n\n  private _isExtendedSelection(event: Event) {\n    return this.shortcuts.extendedSelectionShortcut(event) && this.selectOnDrag;\n  }\n\n  private _normalSelectionMode(selectBox: BoundingBox, item: SelectItemDirective, event: Event) {\n    const inSelection = boxIntersects(selectBox, item.getBoundingClientRect());\n\n    const shouldAdd = inSelection && !item.selected && !this.shortcuts.removeFromSelection(event);\n\n    const shouldRemove =\n      (!inSelection && item.selected && !this.shortcuts.addToSelection(event)) ||\n      (inSelection && item.selected && this.shortcuts.removeFromSelection(event));\n\n    if (shouldAdd) {\n      this._selectItem(item);\n    } else if (shouldRemove) {\n      this._deselectItem(item);\n    }\n  }\n\n  private _extendedSelectionMode(selectBox, item: SelectItemDirective, event: Event) {\n    const inSelection = boxIntersects(selectBox, item.getBoundingClientRect());\n\n    const shoudlAdd =\n      (inSelection && !item.selected && !this.shortcuts.removeFromSelection(event) && !this._tmpItems.has(item)) ||\n      (inSelection && item.selected && this.shortcuts.removeFromSelection(event) && !this._tmpItems.has(item));\n\n    const shouldRemove =\n      (!inSelection && item.selected && this.shortcuts.addToSelection(event) && this._tmpItems.has(item)) ||\n      (!inSelection && !item.selected && this.shortcuts.removeFromSelection(event) && this._tmpItems.has(item));\n\n    if (shoudlAdd) {\n      if (item.selected) {\n        item._deselect();\n      } else {\n        item._select();\n      }\n\n      const action = this.shortcuts.removeFromSelection(event)\n        ? Action.Delete\n        : this.shortcuts.addToSelection(event)\n        ? Action.Add\n        : Action.None;\n\n      this._tmpItems.set(item, action);\n    } else if (shouldRemove) {\n      if (this.shortcuts.removeFromSelection(event)) {\n        item._select();\n      } else {\n        item._deselect();\n      }\n\n      this._tmpItems.delete(item);\n    }\n  }\n\n  private _flushItems() {\n    this._tmpItems.forEach((action, item) => {\n      if (action === Action.Add) {\n        this._selectItem(item);\n      }\n\n      if (action === Action.Delete) {\n        this._deselectItem(item);\n      }\n    });\n\n    this._tmpItems.clear();\n  }\n\n  private _addItem(item: SelectItemDirective, selectedItems: Array<any>) {\n    let success = false;\n\n    if (!this._hasItem(item, selectedItems)) {\n      success = true;\n      selectedItems.push(item.value);\n      this._selectedItems$.next(selectedItems);\n      this.itemSelected.emit(item.value);\n    }\n\n    return success;\n  }\n\n  private _removeItem(item: SelectItemDirective, selectedItems: Array<any>) {\n    let success = false;\n    const value = item instanceof SelectItemDirective ? item.value : item;\n    const index = selectedItems.indexOf(value);\n\n    if (index > -1) {\n      success = true;\n      selectedItems.splice(index, 1);\n      this._selectedItems$.next(selectedItems);\n      this.itemDeselected.emit(value);\n    }\n\n    return success;\n  }\n\n  private _toggleItem(item: SelectItemDirective) {\n    if (item.selected) {\n      this._deselectItem(item);\n    } else {\n      this._selectItem(item);\n    }\n  }\n\n  private _selectItem(item: SelectItemDirective) {\n    this.updateItems$.next({ type: UpdateActions.Add, item });\n  }\n\n  private _deselectItem(item: SelectItemDirective) {\n    this.updateItems$.next({ type: UpdateActions.Remove, item });\n  }\n\n  private _hasItem(item: SelectItemDirective, selectedItems: Array<any>) {\n    return selectedItems.includes(item.value);\n  }\n\n  private _getClosestSelectItem(event: Event): [number, SelectItemDirective] {\n    const target = (event.target as HTMLElement).closest('.dts-select-item');\n    let index = -1;\n    let targetItem = null;\n\n    if (target) {\n      targetItem = target[SELECT_ITEM_INSTANCE];\n      index = this._selectableItems.indexOf(targetItem);\n    }\n\n    return [index, targetItem];\n  }\n\n  private _resetRangeStart() {\n    this._lastRange = [-1, -1];\n    const lastRangeStart = this._getLastRangeSelection();\n\n    if (lastRangeStart && lastRangeStart.rangeStart) {\n      lastRangeStart.toggleRangeStart();\n    }\n  }\n\n  private _getLastRangeSelection(): SelectItemDirective | null {\n    if (this._lastStartIndex >= 0) {\n      return this._selectableItems[this._lastStartIndex];\n    }\n\n    return null;\n  }\n}\n","import { CommonModule } from '@angular/common';\nimport { ModuleWithProviders, NgModule } from '@angular/core';\nimport { DEFAULT_CONFIG } from './config';\nimport { KeyboardEventsService } from './keyboard-events.service';\nimport { DragToSelectConfig } from './models';\nimport { SelectContainerComponent } from './select-container.component';\nimport { SelectItemDirective } from './select-item.directive';\nimport { ShortcutService } from './shortcut.service';\nimport { CONFIG, USER_CONFIG } from './tokens';\nimport { mergeDeep } from './utils';\n\nconst COMPONENTS = [SelectContainerComponent, SelectItemDirective];\n\nfunction configFactory(config: Partial<DragToSelectConfig>) {\n  return mergeDeep(DEFAULT_CONFIG, config);\n}\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [...COMPONENTS],\n  exports: [...COMPONENTS],\n})\nexport class DragToSelectModule {\n  static forRoot(config: Partial<DragToSelectConfig> = {}): ModuleWithProviders<DragToSelectModule> {\n    return {\n      ngModule: DragToSelectModule,\n      providers: [\n        ShortcutService,\n        KeyboardEventsService,\n        { provide: USER_CONFIG, useValue: config },\n        {\n          provide: CONFIG,\n          useFactory: configFactory,\n          deps: [USER_CONFIG],\n        },\n      ],\n    };\n  }\n}\n","/*\n * Public API Surface of ngx-drag-to-select\n */\n\nexport * from './lib/drag-to-select.module';\nexport * from './lib/select-container.component';\nexport * from './lib/select-item.directive';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":";;;;;;;AAEO,MAAM,cAAc,GAAuB;IAChD,aAAa,EAAE,UAAU;IACzB,SAAS,EAAE;QACT,cAAc,EAAE,SAAS;QACzB,gBAAgB,EAAE,KAAK;QACvB,gBAAgB,EAAE,MAAM;QACxB,cAAc,EAAE,OAAO;QACvB,mBAAmB,EAAE,YAAY;KAClC;CACF;;ACXM,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,MAAM,eAAe,GAAG,eAAe;;ACAvC,MAAM,QAAQ,GAAG,CAAC,IAAS;IAChC,OAAO,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC;AACnF,CAAC,CAAC;SAEc,SAAS,CAAC,MAA2B,EAAE,MAA2B;IAChF,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE;QACxC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG;YAC9B,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;gBACzB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;oBAChB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC;iBACtC;gBACD,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;aACrC;iBAAM;gBACL,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;aAC/C;SACF,CAAC,CAAC;KACJ;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,MAAM,cAAc,GAAG,CAAC,SAA4B,EAAE,QAAQ,GAAG,SAAS,EAAE,SAAS,GAAG,UAAU;IACvG,OAAO,SAAS,CAAC,KAAK,GAAG,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC;AACpE,CAAC,CAAC;AAEK,MAAM,cAAc,GAAG,CAAC,MAAc;IAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IAExC,IAAI,CAAC,SAAS,EAAE;QACd,OAAO;KACR;IAED,IAAI,SAAS,CAAC,eAAe,EAAE;QAC7B,SAAS,CAAC,eAAe,EAAE,CAAC;KAC7B;SAAM,IAAI,SAAS,CAAC,KAAK,EAAE;QAC1B,SAAS,CAAC,KAAK,EAAE,CAAC;KACnB;AACH,CAAC,CAAC;AAEK,MAAM,aAAa,GAAG,CAAC,KAAoB,EAAE,GAAgB;IAClE,QACE,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,EAC/G;AACJ,CAAC,CAAC;AAEK,MAAM,aAAa,GAAG,CAAC,IAAiB,EAAE,IAAiB;IAChE,QACE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI;QACnC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM;QAClC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,EAClC;AACJ,CAAC,CAAC;AAEK,MAAM,2BAA2B,GAAG,CAAC,OAAoB;IAC9D,OAAO,OAAO,CAAC,qBAAqB,EAAE,CAAC;AACzC,CAAC,CAAC;AAEK,MAAM,gBAAgB,GAAG,CAAC,KAAiB;IAChD,OAAO;QACL,CAAC,EAAE,KAAK,CAAC,OAAO;QAChB,CAAC,EAAE,KAAK,CAAC,OAAO;KACjB,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,SAAS,GAAG;IACvB,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE;QAC1C,OAAO;YACL,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,CAAC;SACL,CAAC;KACH;IAED,OAAO;QACL,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,UAAU,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU;QAClE,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS;KACjE,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,wBAAwB,GAAG,CAAC,KAAiB,EAAE,SAA8B;IACxF,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,MAAM,UAAU,GAAG,CAAC,SAAS,CAAC,kBAAkB,CAAC,KAAK,GAAG,SAAS,CAAC,WAAW,IAAI,CAAC,CAAC;IACpF,MAAM,UAAU,GAAG,SAAS,CAAC,kBAAkB,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,SAAS,CAAC,kBAAkB,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC;IAE9D,OAAO;QACL,CAAC,EAAE,OAAO,GAAG,UAAU,IAAI,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,UAAU;QAClF,CAAC,EAAE,OAAO,GAAG,UAAU,IAAI,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,SAAS;KACjF,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAE,OAAoB;IACzE,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC3C,OAAO,aAAa,CAAC,UAAU,EAAE,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;AACzE,CAAC;;AC9FM,MAAM,eAAe,GAAG,CAAC,SAA8B;IAC5D,OAAO,CAAC,MAAkC;QACxC,OAAO,MAAM,CAAC,IAAI,CAChB,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;;;YAG7B,MAAM,aAAa,GAAkB,wBAAwB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAEhF,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAErD,OAAO;gBACL,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC;gBACrC,IAAI,EAAE,KAAK,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC;gBACrC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;gBACtB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;gBACxB,OAAO;aACR,CAAC;SACH,CAAC,CACH,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,oBAAoB,GAAG,CAAC,UAAyC,KAAK,CAAC,MAAyB,KAC3G,MAAM,CAAC,IAAI,CACT,cAAc,CAAC,UAAU,CAAC,EAC1B,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,cAAc,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAC1D,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAC3B,CAAC;AAEG,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAiC,KACvE,MAAM,CAAC,IAAI,CACT,oBAAoB,CAAC,CAAC,IAAI,EAAE,IAAI;IAC9B,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;AACjD,CAAC,CAAC,CACH;;MCjCU,qBAAqB;IAQhC,YAAyC,UAAmC;QAAnC,eAAU,GAAV,UAAU,CAAyB;QAC1E,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;YACtC,IAAI,CAAC,0BAA0B,EAAE,CAAC;SACnC;KACF;IAEO,0BAA0B;QAChC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAgB,MAAM,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,GAAG,SAAS,CAAgB,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;;;QAKtE,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAEzE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAErE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAa,MAAM,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,UAAU,GAAG,SAAS,CAAa,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;KAC5E;;kHA3BU,qBAAqB,kBAQZ,WAAW;sHARpB,qBAAqB;2FAArB,qBAAqB;kBADjC,UAAU;;;8BASI,MAAM;+BAAC,WAAW;;;;ACZ1B,MAAM,MAAM,GAAG,IAAI,cAAc,CAAqB,uBAAuB,CAAC,CAAC;AAC/E,MAAM,WAAW,GAAG,IAAI,cAAc,CAAqB,aAAa,CAAC;;MCcnE,oBAAoB,GAAG,MAAM,GAAG;MAMhC,mBAAmB;IAqB9B,YAC0B,MAA0B,EACrB,UAAmC,EACxD,IAAgB,EAChB,QAAmB;QAHH,WAAM,GAAN,MAAM,CAAoB;QACrB,eAAU,GAAV,UAAU,CAAyB;QACxD,SAAI,GAAJ,IAAI,CAAY;QAChB,aAAQ,GAAR,QAAQ,CAAW;QAtB7B,aAAQ,GAAG,KAAK,CAAC;QAGjB,eAAU,GAAG,KAAK,CAAC;QAGV,cAAS,GAAG,IAAI,CAAC;QAM1B,gBAAW,GAAG,KAAK,CAAC;KAWhB;IATJ,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;KACvD;IASD,QAAQ;QACN,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC;KAClD;IAED,SAAS;QACP,IAAI,CAAC,kBAAkB,EAAE,CAAC;KAC3B;IAED,gBAAgB;QACd,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC;KACpC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;KAChC;IAED,qBAAqB;QACnB,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE;YACnE,IAAI,CAAC,2BAA2B,EAAE,CAAC;SACpC;QACD,OAAO,IAAI,CAAC,mBAAmB,CAAC;KACjC;IAED,2BAA2B;QACzB,MAAM,WAAW,GAAG,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACzE,IAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC;QACvC,OAAO,WAAW,CAAC;KACpB;IAED,OAAO;QACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;KACtB;IAED,SAAS;QACP,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;KACvB;IAEO,kBAAkB;QACxB,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;SAC5E;aAAM;YACL,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;SAC/E;KACF;;gHAvEU,mBAAmB,kBAsBpB,MAAM,aACN,WAAW;oGAvBV,mBAAmB;2FAAnB,mBAAmB;kBAJ/B,SAAS;mBAAC;oBACT,QAAQ,EAAE,iBAAiB;oBAC3B,QAAQ,EAAE,eAAe;iBAC1B;;;8BAuBI,MAAM;+BAAC,MAAM;;8BACb,MAAM;+BAAC,WAAW;;yBAjBrB,UAAU;sBADT,WAAW;uBAAC,uBAAuB;gBAI3B,SAAS;sBADjB,WAAW;uBAAC,uBAAuB;gBAG3B,aAAa;sBAArB,KAAK;gBAIN,WAAW;sBAFV,KAAK;;sBACL,WAAW;uBAAC,oBAAoB;;;ACjCnC,IAAY,aAGX;AAHD,WAAY,aAAa;IACvB,+CAAG,CAAA;IACH,qDAAM,CAAA;AACR,CAAC,EAHW,aAAa,KAAb,aAAa,QAGxB;AAmDD,IAAY,MAIX;AAJD,WAAY,MAAM;IAChB,iCAAG,CAAA;IACH,uCAAM,CAAA;IACN,mCAAI,CAAA;AACN,CAAC,EAJW,MAAM,KAAN,MAAM;;ACnDlB,MAAM,mBAAmB,GAAG;IAC1B,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;CACX,CAAC;AAEF,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,QAAQ,GAAG,MAAM,CAAC;AAExB,MAAM,WAAW,GAAG;IAClB,CAAC,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,mBAAmB,GAAG;IAC1B,cAAc,EAAE,IAAI;IACpB,gBAAgB,EAAE,IAAI;IACtB,gBAAgB,EAAE,IAAI;IACtB,cAAc,EAAE,IAAI;IACpB,mBAAmB,EAAE,IAAI;CAC1B,CAAC;AAEF,MAAM,YAAY,GAAG,mBAAmB,CAAC;MAQ5B,eAAe;IAK1B,YAC+B,UAAmC,EAChD,MAA0B,EAClC,cAAqC;QAFhB,eAAU,GAAV,UAAU,CAAyB;QAExD,mBAAc,GAAd,cAAc,CAAuB;QAPvC,eAAU,GAAkC,EAAE,CAAC;QAE/C,oBAAe,GAAyB,IAAI,GAAG,EAAE,CAAC;QAOxD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,0BAA0B,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEpE,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAChD,GAAG,CAA0B,CAAC,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAC/E,CAAC;YAEF,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAC5C,GAAG,CAA0B,CAAC,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAChF,CAAC;YAEF,KAAK,CAAW,QAAQ,EAAE,MAAM,CAAC;iBAC9B,IAAI,CACH,oBAAoB,CAAC,CAAC,IAAI,EAAE,IAAI;gBAC9B,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;aACjE,CAAC,CACH;iBACA,SAAS,CAAC,CAAC,QAAQ;gBAClB,IAAI,QAAQ,CAAC,OAAO,EAAE;oBACpB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;iBAC/C;qBAAM;oBACL,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;iBAC5C;aACF,CAAC,CAAC;SACN;KACF;IAED,gBAAgB,CAAC,KAAY;QAC3B,OAAO,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;KAC3D;IAED,cAAc,CAAC,KAAY;QACzB,OAAO,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;KACzD;IAED,gBAAgB,CAAC,KAAY;QAC3B,OAAO,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;KAC3D;IAED,cAAc,CAAC,KAAY;QACzB,OAAO,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;KACzD;IAED,mBAAmB,CAAC,KAAY;QAC9B,OAAO,IAAI,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;KAC9D;IAED,yBAAyB,CAAC,KAAY;QACpC,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;KACtE;IAEO,0BAA0B,CAAC,SAAoC;QACrE,MAAM,WAAW,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,CAAC,GAAG,EAAE,mBAAmB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;YAClE,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE;gBACnC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC;aACzE;YAED,mBAAmB;iBAChB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;iBACjB,KAAK,CAAC,GAAG,CAAC;iBACV,OAAO,CAAC,CAAC,QAAQ;gBAChB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE;oBACrB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;iBACvB;gBAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAEnE,WAAW,CAAC,OAAO,CAAC,CAAC,UAAU;oBAC7B,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;oBAE1D,IAAI,cAAc,EAAE;wBAClB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB,CA