{"version":3,"file":"sequence-manager.cjs","names":["#instance","Store","#platform","detectPlatform","parseHotkey","#findConflictingSequence","formatHotkeySequence","#unregister","getDefaultIgnoreInputs","defaultHotkeyOptions","#registrations","#targetRegistrations","#ensureListenersForTarget","#removeListenersForTarget","#targetListeners","#createTargetKeyDownHandler","#createTargetKeyUpHandler","#processTargetEvent","isModifierKey","normalizeKeyName","isEventForTarget","shouldIgnoreInputEvent","#syncRegistrationView","matchesKeyboardEvent"],"sources":["../src/sequence-manager.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport { formatHotkeySequence } from './format'\nimport { detectPlatform, normalizeKeyName } from './constants'\nimport { isModifierKey, parseHotkey } from './parse'\nimport { matchesKeyboardEvent } from './match'\nimport {\n  defaultHotkeyOptions,\n  getDefaultIgnoreInputs,\n  handleConflict,\n  isEventForTarget,\n  shouldIgnoreInputEvent,\n} from './manager.utils'\nimport type { HotkeyOptions } from './hotkey-manager'\nimport type {\n  Hotkey,\n  HotkeyCallback,\n  HotkeyCallbackContext,\n  ParsedHotkey,\n} from './hotkey'\n\ntype Target = HTMLElement | Document | Window\n\n/**\n * Options for hotkey sequence matching.\n * Extends HotkeyOptions but excludes requireReset (not applicable to sequences).\n */\nexport interface SequenceOptions extends Omit<HotkeyOptions, 'requireReset'> {\n  /** Timeout between keys in milliseconds. Default: 1000 */\n  timeout?: number\n}\n\n/**\n * A sequence of hotkeys for Vim-style shortcuts.\n *\n * Each element is one step (a `Hotkey` string). Steps may include modifiers;\n * the same modifier can appear on consecutive steps (e.g. `Shift+R` then\n * `Shift+T`). Modifier-only key events do not advance or reset matching—see\n * `SequenceManager`.\n *\n * @example\n * ```ts\n * const gotoTop: HotkeySequence = ['G', 'G']  // gg\n * const deleteLine: HotkeySequence = ['D', 'D']  // dd\n * const deleteWord: HotkeySequence = ['D', 'I', 'W']  // diw\n * const chainedShift: HotkeySequence = ['Shift+R', 'Shift+T']\n * ```\n */\nexport type HotkeySequence = Array<Hotkey>\n\n/**\n * Default timeout between keys in a sequence (in milliseconds).\n * Exported for consumers that display sequence state (e.g. devtools).\n */\nexport const DEFAULT_SEQUENCE_TIMEOUT = 1000\n\nlet sequenceIdCounter = 0\n\n/**\n * Generates a unique ID for sequence registrations.\n */\nfunction generateSequenceId(): string {\n  return `sequence_${++sequenceIdCounter}`\n}\n\n/**\n * Returns a canonical string for sequence conflict comparison.\n */\nfunction sequenceKey(sequence: HotkeySequence): string {\n  return sequence.join('|')\n}\n\n/**\n * View of a sequence registration for devtools display.\n * Progress fields reflect an in-progress match (between first key and completion or timeout).\n */\nexport interface SequenceRegistrationView {\n  id: string\n  sequence: HotkeySequence\n  options: SequenceOptions\n  target: Target\n  triggerCount: number\n  /** Whether this sequence has been triggered at least once. */\n  hasFired: boolean\n  /** Steps matched in the current attempt (0 when idle or just completed). */\n  matchedStepCount: number\n  /** `Date.now()` when the last step in the current attempt matched; 0 if none. */\n  partialMatchLastKeyTime: number\n}\n\n/**\n * Internal representation of a sequence registration.\n */\ninterface SequenceRegistration {\n  id: string\n  sequence: HotkeySequence\n  parsedSequence: Array<ParsedHotkey>\n  callback: HotkeyCallback\n  options: SequenceOptions\n  target: Target\n  currentIndex: number\n  lastKeyTime: number\n  triggerCount: number\n  hasFired: boolean\n}\n\n/**\n * A handle returned from SequenceManager.register() that allows updating\n * the callback and options without re-registering the sequence.\n *\n * @example\n * ```ts\n * const handle = manager.register(['G', 'G'], callback, options)\n *\n * handle.callback = newCallback\n * handle.setOptions({ timeout: 500 })\n * handle.unregister()\n * ```\n */\nexport interface SequenceRegistrationHandle {\n  readonly id: string\n  readonly isActive: boolean\n  callback: HotkeyCallback\n  setOptions: (options: Partial<SequenceOptions>) => void\n  unregister: () => void\n}\n\n/**\n * Manages keyboard sequence matching for Vim-style shortcuts.\n *\n * This class allows registering multi-key sequences like 'g g' or 'd d'\n * that trigger callbacks when the full sequence is pressed within\n * a configurable timeout.\n *\n * Modifier-only `keydown` / `keyup` events (Shift, Control, Alt, or Meta\n * alone) are not processed: they neither match a step nor reset progress.\n * That supports chained modifier chords (e.g. `Shift+R` then `Shift+T`) when\n * the user presses a modifier alone between steps.\n *\n * @example\n * ```ts\n * const matcher = SequenceManager.getInstance()\n *\n * // Register 'g g' to go to top\n * const unregister = matcher.register(['G', 'G'], (event, context) => {\n *   scrollToTop()\n * }, { timeout: 500 })\n *\n * // Later, to unregister:\n * unregister()\n * ```\n */\n/**\n * Builds a devtools view from an internal registration.\n */\nfunction toRegistrationView(\n  reg: SequenceRegistration,\n): SequenceRegistrationView {\n  const len = reg.parsedSequence.length\n  const inProgress = reg.currentIndex > 0 && reg.currentIndex < len\n  return {\n    id: reg.id,\n    sequence: reg.sequence,\n    options: reg.options,\n    target: reg.target,\n    triggerCount: reg.triggerCount,\n    hasFired: reg.hasFired,\n    matchedStepCount: inProgress ? reg.currentIndex : 0,\n    partialMatchLastKeyTime: inProgress ? reg.lastKeyTime : 0,\n  }\n}\n\nexport class SequenceManager {\n  static #instance: SequenceManager | null = null\n\n  /**\n   * The TanStack Store containing sequence registration views for devtools.\n   * Subscribe to this to observe registration changes.\n   */\n  readonly registrations: Store<Map<string, SequenceRegistrationView>> =\n    new Store(new Map())\n\n  #registrations: Map<string, SequenceRegistration> = new Map()\n  #targetListeners: Map<\n    Target,\n    {\n      keydown: (event: KeyboardEvent) => void\n      keyup: (event: KeyboardEvent) => void\n    }\n  > = new Map()\n  #targetRegistrations: Map<Target, Set<string>> = new Map()\n  #platform: 'mac' | 'windows' | 'linux'\n\n  private constructor() {\n    this.#platform = detectPlatform()\n  }\n\n  /**\n   * Gets the singleton instance of SequenceManager.\n   */\n  static getInstance(): SequenceManager {\n    if (!SequenceManager.#instance) {\n      SequenceManager.#instance = new SequenceManager()\n    }\n    return SequenceManager.#instance\n  }\n\n  /**\n   * Resets the singleton instance. Useful for testing.\n   */\n  static resetInstance(): void {\n    if (SequenceManager.#instance) {\n      SequenceManager.#instance.destroy()\n      SequenceManager.#instance = null\n    }\n  }\n\n  #syncRegistrationView(registration: SequenceRegistration): void {\n    this.registrations.setState((prev) =>\n      new Map(prev).set(registration.id, toRegistrationView(registration)),\n    )\n  }\n\n  /**\n   * Registers a hotkey sequence handler.\n   *\n   * @param sequence - Array of hotkey strings that form the sequence\n   * @param callback - Function to call when the sequence is completed\n   * @param options - Options for the sequence behavior\n   * @returns A handle to update or unregister the sequence\n   */\n  register(\n    sequence: HotkeySequence,\n    callback: HotkeyCallback,\n    options: SequenceOptions = {},\n  ): SequenceRegistrationHandle {\n    if (sequence.length === 0) {\n      throw new Error('Sequence must contain at least one hotkey')\n    }\n\n    const id = generateSequenceId()\n    const platform = options.platform ?? this.#platform\n    const parsedSequence = sequence.map((hotkey) =>\n      parseHotkey(hotkey, platform),\n    )\n\n    // Resolve target: default to document if not provided or null\n    const target: Target =\n      options.target ??\n      (typeof document !== 'undefined' ? document : ({} as Document))\n\n    // Resolve conflict behavior\n    const conflictBehavior = options.conflictBehavior ?? 'warn'\n\n    // Check for existing registrations with the same sequence and target\n    const conflictingRegistration = this.#findConflictingSequence(\n      sequence,\n      target,\n    )\n\n    if (conflictingRegistration) {\n      handleConflict(\n        conflictingRegistration.id,\n        formatHotkeySequence(sequence),\n        conflictBehavior,\n        (regId) => this.#unregister(regId),\n      )\n    }\n\n    const firstStep = parsedSequence[0]!\n    const resolvedIgnoreInputs =\n      options.ignoreInputs ?? getDefaultIgnoreInputs(firstStep)\n\n    const baseOptions = {\n      ...defaultHotkeyOptions,\n      timeout: DEFAULT_SEQUENCE_TIMEOUT,\n      ...options,\n      platform,\n      ignoreInputs: resolvedIgnoreInputs,\n    }\n\n    const registration: SequenceRegistration = {\n      id,\n      sequence,\n      parsedSequence,\n      callback,\n      options: baseOptions,\n      target,\n      currentIndex: 0,\n      lastKeyTime: 0,\n      triggerCount: 0,\n      hasFired: false,\n    }\n\n    this.#registrations.set(id, registration)\n    this.registrations.setState((prev) =>\n      new Map(prev).set(id, toRegistrationView(registration)),\n    )\n\n    // Track registration for this target\n    if (!this.#targetRegistrations.has(target)) {\n      this.#targetRegistrations.set(target, new Set())\n    }\n    this.#targetRegistrations.get(target)!.add(id)\n\n    // Ensure listeners are attached for this target\n    this.#ensureListenersForTarget(target)\n\n    const manager = this\n    const handle: SequenceRegistrationHandle = {\n      get id() {\n        return id\n      },\n      get isActive() {\n        return manager.#registrations.has(id)\n      },\n      get callback() {\n        const reg = manager.#registrations.get(id)\n        return reg?.callback ?? callback\n      },\n      set callback(newCallback: HotkeyCallback) {\n        const reg = manager.#registrations.get(id)\n        if (reg) {\n          reg.callback = newCallback\n        }\n      },\n      setOptions: (newOptions: Partial<SequenceOptions>) => {\n        const reg = manager.#registrations.get(id)\n        if (reg) {\n          reg.options = { ...reg.options, ...newOptions }\n          manager.registrations.setState((prev) =>\n            new Map(prev).set(id, toRegistrationView(reg)),\n          )\n        }\n      },\n      unregister: () => {\n        manager.#unregister(id)\n      },\n    }\n\n    return handle\n  }\n\n  /**\n   * Unregisters a sequence by its registration ID.\n   */\n  #unregister(id: string): void {\n    const registration = this.#registrations.get(id)\n    if (!registration) {\n      return\n    }\n\n    const target = registration.target\n\n    this.#registrations.delete(id)\n    this.registrations.setState((prev) => {\n      const next = new Map(prev)\n      next.delete(id)\n      return next\n    })\n\n    // Remove from target registrations tracking\n    const targetRegs = this.#targetRegistrations.get(target)\n    if (targetRegs) {\n      targetRegs.delete(id)\n      if (targetRegs.size === 0) {\n        this.#removeListenersForTarget(target)\n      }\n    }\n  }\n\n  /**\n   * Ensures event listeners are attached for a specific target.\n   */\n  #ensureListenersForTarget(target: Target): void {\n    if (typeof document === 'undefined') {\n      return // SSR safety\n    }\n\n    if (this.#targetListeners.has(target)) {\n      return\n    }\n\n    const keydownHandler = this.#createTargetKeyDownHandler(target)\n    const keyupHandler = this.#createTargetKeyUpHandler(target)\n\n    target.addEventListener('keydown', keydownHandler as EventListener)\n    target.addEventListener('keyup', keyupHandler as EventListener)\n\n    this.#targetListeners.set(target, {\n      keydown: keydownHandler,\n      keyup: keyupHandler,\n    })\n  }\n\n  /**\n   * Removes event listeners for a specific target.\n   */\n  #removeListenersForTarget(target: Target): void {\n    if (typeof document === 'undefined') {\n      return\n    }\n\n    const listeners = this.#targetListeners.get(target)\n    if (!listeners) {\n      return\n    }\n\n    target.removeEventListener('keydown', listeners.keydown as EventListener)\n    target.removeEventListener('keyup', listeners.keyup as EventListener)\n\n    this.#targetListeners.delete(target)\n    this.#targetRegistrations.delete(target)\n  }\n\n  /**\n   * Creates a keydown handler for a specific target.\n   */\n  #createTargetKeyDownHandler(target: Target): (event: KeyboardEvent) => void {\n    return (event: KeyboardEvent) => {\n      this.#processTargetEvent(event, target, 'keydown')\n    }\n  }\n\n  /**\n   * Creates a keyup handler for a specific target.\n   */\n  #createTargetKeyUpHandler(target: Target): (event: KeyboardEvent) => void {\n    return (event: KeyboardEvent) => {\n      this.#processTargetEvent(event, target, 'keyup')\n    }\n  }\n\n  /**\n   * Processes keyboard events for a specific target and event type.\n   */\n  #processTargetEvent(\n    event: KeyboardEvent,\n    target: Target,\n    eventType: 'keydown' | 'keyup',\n  ): void {\n    // Skip modifier-only events so pressing e.g. Shift before Shift+C does not reset the sequence.\n    if (isModifierKey(normalizeKeyName(event.key))) {\n      return\n    }\n\n    const targetRegs = this.#targetRegistrations.get(target)\n    if (!targetRegs) {\n      return\n    }\n\n    const now = Date.now()\n\n    registrationIds: for (const id of targetRegs) {\n      const registration = this.#registrations.get(id)\n      if (!registration) {\n        continue\n      }\n\n      if (!isEventForTarget(event, target)) {\n        continue\n      }\n\n      if (!registration.options.enabled) {\n        continue\n      }\n\n      // Check if we should ignore input elements (defaults to true)\n      if (registration.options.ignoreInputs !== false) {\n        if (shouldIgnoreInputEvent(event, target, registration.target)) {\n          continue registrationIds\n        }\n      }\n\n      // Only process registrations that listen for this event type\n      if (registration.options.eventType !== eventType) {\n        continue\n      }\n\n      const timeout = registration.options.timeout ?? DEFAULT_SEQUENCE_TIMEOUT\n\n      // Check if sequence has timed out\n      if (\n        registration.currentIndex > 0 &&\n        now - registration.lastKeyTime > timeout\n      ) {\n        registration.currentIndex = 0\n        this.#syncRegistrationView(registration)\n      }\n\n      const expectedHotkey =\n        registration.parsedSequence[registration.currentIndex]\n      if (!expectedHotkey) {\n        continue\n      }\n\n      if (\n        matchesKeyboardEvent(\n          event,\n          expectedHotkey,\n          registration.options.platform,\n        )\n      ) {\n        registration.lastKeyTime = now\n        registration.currentIndex++\n\n        if (registration.currentIndex >= registration.parsedSequence.length) {\n          if (registration.options.preventDefault) {\n            event.preventDefault()\n          }\n          if (registration.options.stopPropagation) {\n            event.stopPropagation()\n          }\n\n          const context: HotkeyCallbackContext = {\n            hotkey: registration.sequence.join(' ') as Hotkey,\n            parsedHotkey:\n              registration.parsedSequence[\n                registration.parsedSequence.length - 1\n              ]!,\n          }\n\n          registration.triggerCount++\n          registration.hasFired = true\n          registration.currentIndex = 0\n\n          this.#syncRegistrationView(registration)\n\n          registration.callback(event, context)\n        } else {\n          this.#syncRegistrationView(registration)\n        }\n      } else if (registration.currentIndex > 0) {\n        const firstHotkey = registration.parsedSequence[0]!\n        if (\n          matchesKeyboardEvent(\n            event,\n            firstHotkey,\n            registration.options.platform,\n          )\n        ) {\n          registration.currentIndex = 1\n          registration.lastKeyTime = now\n        } else {\n          registration.currentIndex = 0\n        }\n        this.#syncRegistrationView(registration)\n      }\n    }\n  }\n\n  /**\n   * Finds an existing registration with the same sequence and target.\n   */\n  #findConflictingSequence(\n    sequence: HotkeySequence,\n    target: Target,\n  ): SequenceRegistration | null {\n    const key = sequenceKey(sequence)\n    for (const registration of this.#registrations.values()) {\n      if (\n        sequenceKey(registration.sequence) === key &&\n        registration.target === target\n      ) {\n        return registration\n      }\n    }\n    return null\n  }\n\n  /**\n   * Resets all sequence progress.\n   */\n  resetAll(): void {\n    for (const registration of this.#registrations.values()) {\n      registration.currentIndex = 0\n      registration.lastKeyTime = 0\n      this.#syncRegistrationView(registration)\n    }\n  }\n\n  /**\n   * Triggers a sequence's callback programmatically from devtools.\n   * Creates a synthetic KeyboardEvent from the last key in the sequence.\n   *\n   * @param id - The registration ID to trigger\n   * @returns True if the registration was found and triggered\n   */\n  triggerSequence(id: string): boolean {\n    const registration = this.#registrations.get(id)\n    if (!registration) {\n      return false\n    }\n\n    const lastParsed =\n      registration.parsedSequence[registration.parsedSequence.length - 1]\n    if (!lastParsed) {\n      return false\n    }\n\n    const syntheticEvent = new KeyboardEvent(\n      registration.options.eventType ?? 'keydown',\n      {\n        key: lastParsed.key,\n        ctrlKey: lastParsed.ctrl,\n        shiftKey: lastParsed.shift,\n        altKey: lastParsed.alt,\n        metaKey: lastParsed.meta,\n        bubbles: true,\n        cancelable: true,\n      },\n    )\n\n    registration.triggerCount++\n    registration.hasFired = true\n\n    this.#syncRegistrationView(registration)\n\n    const context: HotkeyCallbackContext = {\n      hotkey: registration.sequence.join(' ') as Hotkey,\n      parsedHotkey: lastParsed,\n    }\n\n    registration.callback(syntheticEvent, context)\n\n    return true\n  }\n\n  /**\n   * Gets the number of registered sequences.\n   */\n  getRegistrationCount(): number {\n    return this.#registrations.size\n  }\n\n  /**\n   * Destroys the manager and removes all listeners.\n   */\n  destroy(): void {\n    for (const target of this.#targetListeners.keys()) {\n      this.#removeListenersForTarget(target)\n    }\n    this.#registrations.clear()\n    this.registrations.setState(() => new Map())\n  }\n}\n\n/**\n * Gets the singleton SequenceManager instance.\n * Convenience function for accessing the manager.\n */\nexport function getSequenceManager(): SequenceManager {\n  return SequenceManager.getInstance()\n}\n\n/**\n * Creates a simple sequence matcher for one-off use.\n *\n * This is a low-level helper that does not support ignoreInputs, target,\n * or other HotkeyOptions. Callers must handle input filtering themselves\n * if attaching to document.\n *\n * @param sequence - The sequence of hotkeys to match\n * @param options - Options including timeout\n * @returns An object with match() and reset() methods\n *\n * @example\n * ```ts\n * const matcher = createSequenceMatcher(['G', 'G'], { timeout: 500 })\n *\n * document.addEventListener('keydown', (event) => {\n *   if (matcher.match(event)) {\n *     console.log('Sequence matched!')\n *   }\n * })\n * ```\n */\nexport function createSequenceMatcher(\n  sequence: HotkeySequence,\n  options: { timeout?: number; platform?: 'mac' | 'windows' | 'linux' } = {},\n): {\n  match: (event: KeyboardEvent) => boolean\n  reset: () => void\n  getProgress: () => number\n} {\n  const platform = options.platform ?? detectPlatform()\n  const timeout = options.timeout ?? DEFAULT_SEQUENCE_TIMEOUT\n  const parsedSequence = sequence.map((hotkey) => parseHotkey(hotkey, platform))\n\n  let currentIndex = 0\n  let lastKeyTime = 0\n\n  return {\n    match(event: KeyboardEvent): boolean {\n      const now = Date.now()\n\n      if (currentIndex > 0 && now - lastKeyTime > timeout) {\n        currentIndex = 0\n      }\n\n      const expected = parsedSequence[currentIndex]\n      if (!expected) {\n        return false\n      }\n\n      if (matchesKeyboardEvent(event, expected, platform)) {\n        lastKeyTime = now\n        currentIndex++\n\n        if (currentIndex >= parsedSequence.length) {\n          currentIndex = 0\n          return true\n        }\n      } else if (currentIndex > 0) {\n        if (matchesKeyboardEvent(event, parsedSequence[0]!, platform)) {\n          currentIndex = 1\n          lastKeyTime = now\n        } else {\n          currentIndex = 0\n        }\n      }\n\n      return false\n    },\n\n    reset(): void {\n      currentIndex = 0\n      lastKeyTime = 0\n    },\n\n    getProgress(): number {\n      return currentIndex\n    },\n  }\n}\n"],"mappings":";;;;;;;;;;;;AAqDA,MAAa,2BAA2B;AAExC,IAAI,oBAAoB;;;;AAKxB,SAAS,qBAA6B;AACpC,QAAO,YAAY,EAAE;;;;;AAMvB,SAAS,YAAY,UAAkC;AACrD,QAAO,SAAS,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsF3B,SAAS,mBACP,KAC0B;CAC1B,MAAM,MAAM,IAAI,eAAe;CAC/B,MAAM,aAAa,IAAI,eAAe,KAAK,IAAI,eAAe;AAC9D,QAAO;EACL,IAAI,IAAI;EACR,UAAU,IAAI;EACd,SAAS,IAAI;EACb,QAAQ,IAAI;EACZ,cAAc,IAAI;EAClB,UAAU,IAAI;EACd,kBAAkB,aAAa,IAAI,eAAe;EAClD,yBAAyB,aAAa,IAAI,cAAc;EACzD;;AAGH,IAAa,kBAAb,MAAa,gBAAgB;CAC3B,QAAOA,WAAoC;CAS3C,iCAAoD,IAAI,KAAK;CAC7D,mCAMI,IAAI,KAAK;CACb,uCAAiD,IAAI,KAAK;CAC1D;CAEA,AAAQ,cAAc;uBAbpB,IAAIC,sCAAM,IAAI,KAAK,CAAC;AAcpB,QAAKC,WAAYC,kCAAgB;;;;;CAMnC,OAAO,cAA+B;AACpC,MAAI,CAAC,iBAAgBH,SACnB,kBAAgBA,WAAY,IAAI,iBAAiB;AAEnD,SAAO,iBAAgBA;;;;;CAMzB,OAAO,gBAAsB;AAC3B,MAAI,iBAAgBA,UAAW;AAC7B,oBAAgBA,SAAU,SAAS;AACnC,oBAAgBA,WAAY;;;CAIhC,sBAAsB,cAA0C;AAC9D,OAAK,cAAc,UAAU,SAC3B,IAAI,IAAI,KAAK,CAAC,IAAI,aAAa,IAAI,mBAAmB,aAAa,CAAC,CACrE;;;;;;;;;;CAWH,SACE,UACA,UACA,UAA2B,EAAE,EACD;AAC5B,MAAI,SAAS,WAAW,EACtB,OAAM,IAAI,MAAM,4CAA4C;EAG9D,MAAM,KAAK,oBAAoB;EAC/B,MAAM,WAAW,QAAQ,YAAY,MAAKE;EAC1C,MAAM,iBAAiB,SAAS,KAAK,WACnCE,0BAAY,QAAQ,SAAS,CAC9B;EAGD,MAAM,SACJ,QAAQ,WACP,OAAO,aAAa,cAAc,WAAY,EAAE;EAGnD,MAAM,mBAAmB,QAAQ,oBAAoB;EAGrD,MAAM,0BAA0B,MAAKC,wBACnC,UACA,OACD;AAED,MAAI,wBACF,sCACE,wBAAwB,IACxBC,oCAAqB,SAAS,EAC9B,mBACC,UAAU,MAAKC,WAAY,MAAM,CACnC;EAGH,MAAM,YAAY,eAAe;EACjC,MAAM,uBACJ,QAAQ,gBAAgBC,6CAAuB,UAAU;EAU3D,MAAM,eAAqC;GACzC;GACA;GACA;GACA;GACA,SAbkB;IAClB,GAAGC;IACH,SAAS;IACT,GAAG;IACH;IACA,cAAc;IACf;GAQC;GACA,cAAc;GACd,aAAa;GACb,cAAc;GACd,UAAU;GACX;AAED,QAAKC,cAAe,IAAI,IAAI,aAAa;AACzC,OAAK,cAAc,UAAU,SAC3B,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,mBAAmB,aAAa,CAAC,CACxD;AAGD,MAAI,CAAC,MAAKC,oBAAqB,IAAI,OAAO,CACxC,OAAKA,oBAAqB,IAAI,wBAAQ,IAAI,KAAK,CAAC;AAElD,QAAKA,oBAAqB,IAAI,OAAO,CAAE,IAAI,GAAG;AAG9C,QAAKC,yBAA0B,OAAO;EAEtC,MAAM,UAAU;AAgChB,SA/B2C;GACzC,IAAI,KAAK;AACP,WAAO;;GAET,IAAI,WAAW;AACb,WAAO,SAAQF,cAAe,IAAI,GAAG;;GAEvC,IAAI,WAAW;AAEb,WADY,SAAQA,cAAe,IAAI,GAAG,EAC9B,YAAY;;GAE1B,IAAI,SAAS,aAA6B;IACxC,MAAM,MAAM,SAAQA,cAAe,IAAI,GAAG;AAC1C,QAAI,IACF,KAAI,WAAW;;GAGnB,aAAa,eAAyC;IACpD,MAAM,MAAM,SAAQA,cAAe,IAAI,GAAG;AAC1C,QAAI,KAAK;AACP,SAAI,UAAU;MAAE,GAAG,IAAI;MAAS,GAAG;MAAY;AAC/C,aAAQ,cAAc,UAAU,SAC9B,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,mBAAmB,IAAI,CAAC,CAC/C;;;GAGL,kBAAkB;AAChB,aAAQH,WAAY,GAAG;;GAE1B;;;;;CAQH,YAAY,IAAkB;EAC5B,MAAM,eAAe,MAAKG,cAAe,IAAI,GAAG;AAChD,MAAI,CAAC,aACH;EAGF,MAAM,SAAS,aAAa;AAE5B,QAAKA,cAAe,OAAO,GAAG;AAC9B,OAAK,cAAc,UAAU,SAAS;GACpC,MAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,QAAK,OAAO,GAAG;AACf,UAAO;IACP;EAGF,MAAM,aAAa,MAAKC,oBAAqB,IAAI,OAAO;AACxD,MAAI,YAAY;AACd,cAAW,OAAO,GAAG;AACrB,OAAI,WAAW,SAAS,EACtB,OAAKE,yBAA0B,OAAO;;;;;;CAQ5C,0BAA0B,QAAsB;AAC9C,MAAI,OAAO,aAAa,YACtB;AAGF,MAAI,MAAKC,gBAAiB,IAAI,OAAO,CACnC;EAGF,MAAM,iBAAiB,MAAKC,2BAA4B,OAAO;EAC/D,MAAM,eAAe,MAAKC,yBAA0B,OAAO;AAE3D,SAAO,iBAAiB,WAAW,eAAgC;AACnE,SAAO,iBAAiB,SAAS,aAA8B;AAE/D,QAAKF,gBAAiB,IAAI,QAAQ;GAChC,SAAS;GACT,OAAO;GACR,CAAC;;;;;CAMJ,0BAA0B,QAAsB;AAC9C,MAAI,OAAO,aAAa,YACtB;EAGF,MAAM,YAAY,MAAKA,gBAAiB,IAAI,OAAO;AACnD,MAAI,CAAC,UACH;AAGF,SAAO,oBAAoB,WAAW,UAAU,QAAyB;AACzE,SAAO,oBAAoB,SAAS,UAAU,MAAuB;AAErE,QAAKA,gBAAiB,OAAO,OAAO;AACpC,QAAKH,oBAAqB,OAAO,OAAO;;;;;CAM1C,4BAA4B,QAAgD;AAC1E,UAAQ,UAAyB;AAC/B,SAAKM,mBAAoB,OAAO,QAAQ,UAAU;;;;;;CAOtD,0BAA0B,QAAgD;AACxE,UAAQ,UAAyB;AAC/B,SAAKA,mBAAoB,OAAO,QAAQ,QAAQ;;;;;;CAOpD,oBACE,OACA,QACA,WACM;AAEN,MAAIC,4BAAcC,mCAAiB,MAAM,IAAI,CAAC,CAC5C;EAGF,MAAM,aAAa,MAAKR,oBAAqB,IAAI,OAAO;AACxD,MAAI,CAAC,WACH;EAGF,MAAM,MAAM,KAAK,KAAK;AAEtB,kBAAiB,MAAK,MAAM,MAAM,YAAY;GAC5C,MAAM,eAAe,MAAKD,cAAe,IAAI,GAAG;AAChD,OAAI,CAAC,aACH;AAGF,OAAI,CAACU,uCAAiB,OAAO,OAAO,CAClC;AAGF,OAAI,CAAC,aAAa,QAAQ,QACxB;AAIF,OAAI,aAAa,QAAQ,iBAAiB,OACxC;QAAIC,6CAAuB,OAAO,QAAQ,aAAa,OAAO,CAC5D,UAAS;;AAKb,OAAI,aAAa,QAAQ,cAAc,UACrC;GAGF,MAAM,UAAU,aAAa,QAAQ;AAGrC,OACE,aAAa,eAAe,KAC5B,MAAM,aAAa,cAAc,SACjC;AACA,iBAAa,eAAe;AAC5B,UAAKC,qBAAsB,aAAa;;GAG1C,MAAM,iBACJ,aAAa,eAAe,aAAa;AAC3C,OAAI,CAAC,eACH;AAGF,OACEC,mCACE,OACA,gBACA,aAAa,QAAQ,SACtB,EACD;AACA,iBAAa,cAAc;AAC3B,iBAAa;AAEb,QAAI,aAAa,gBAAgB,aAAa,eAAe,QAAQ;AACnE,SAAI,aAAa,QAAQ,eACvB,OAAM,gBAAgB;AAExB,SAAI,aAAa,QAAQ,gBACvB,OAAM,iBAAiB;KAGzB,MAAM,UAAiC;MACrC,QAAQ,aAAa,SAAS,KAAK,IAAI;MACvC,cACE,aAAa,eACX,aAAa,eAAe,SAAS;MAE1C;AAED,kBAAa;AACb,kBAAa,WAAW;AACxB,kBAAa,eAAe;AAE5B,WAAKD,qBAAsB,aAAa;AAExC,kBAAa,SAAS,OAAO,QAAQ;UAErC,OAAKA,qBAAsB,aAAa;cAEjC,aAAa,eAAe,GAAG;IACxC,MAAM,cAAc,aAAa,eAAe;AAChD,QACEC,mCACE,OACA,aACA,aAAa,QAAQ,SACtB,EACD;AACA,kBAAa,eAAe;AAC5B,kBAAa,cAAc;UAE3B,cAAa,eAAe;AAE9B,UAAKD,qBAAsB,aAAa;;;;;;;CAQ9C,yBACE,UACA,QAC6B;EAC7B,MAAM,MAAM,YAAY,SAAS;AACjC,OAAK,MAAM,gBAAgB,MAAKZ,cAAe,QAAQ,CACrD,KACE,YAAY,aAAa,SAAS,KAAK,OACvC,aAAa,WAAW,OAExB,QAAO;AAGX,SAAO;;;;;CAMT,WAAiB;AACf,OAAK,MAAM,gBAAgB,MAAKA,cAAe,QAAQ,EAAE;AACvD,gBAAa,eAAe;AAC5B,gBAAa,cAAc;AAC3B,SAAKY,qBAAsB,aAAa;;;;;;;;;;CAW5C,gBAAgB,IAAqB;EACnC,MAAM,eAAe,MAAKZ,cAAe,IAAI,GAAG;AAChD,MAAI,CAAC,aACH,QAAO;EAGT,MAAM,aACJ,aAAa,eAAe,aAAa,eAAe,SAAS;AACnE,MAAI,CAAC,WACH,QAAO;EAGT,MAAM,iBAAiB,IAAI,cACzB,aAAa,QAAQ,aAAa,WAClC;GACE,KAAK,WAAW;GAChB,SAAS,WAAW;GACpB,UAAU,WAAW;GACrB,QAAQ,WAAW;GACnB,SAAS,WAAW;GACpB,SAAS;GACT,YAAY;GACb,CACF;AAED,eAAa;AACb,eAAa,WAAW;AAExB,QAAKY,qBAAsB,aAAa;EAExC,MAAM,UAAiC;GACrC,QAAQ,aAAa,SAAS,KAAK,IAAI;GACvC,cAAc;GACf;AAED,eAAa,SAAS,gBAAgB,QAAQ;AAE9C,SAAO;;;;;CAMT,uBAA+B;AAC7B,SAAO,MAAKZ,cAAe;;;;;CAM7B,UAAgB;AACd,OAAK,MAAM,UAAU,MAAKI,gBAAiB,MAAM,CAC/C,OAAKD,yBAA0B,OAAO;AAExC,QAAKH,cAAe,OAAO;AAC3B,OAAK,cAAc,+BAAe,IAAI,KAAK,CAAC;;;;;;;AAQhD,SAAgB,qBAAsC;AACpD,QAAO,gBAAgB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;AAyBtC,SAAgB,sBACd,UACA,UAAwE,EAAE,EAK1E;CACA,MAAM,WAAW,QAAQ,YAAYP,kCAAgB;CACrD,MAAM,UAAU,QAAQ;CACxB,MAAM,iBAAiB,SAAS,KAAK,WAAWC,0BAAY,QAAQ,SAAS,CAAC;CAE9E,IAAI,eAAe;CACnB,IAAI,cAAc;AAElB,QAAO;EACL,MAAM,OAA+B;GACnC,MAAM,MAAM,KAAK,KAAK;AAEtB,OAAI,eAAe,KAAK,MAAM,cAAc,QAC1C,gBAAe;GAGjB,MAAM,WAAW,eAAe;AAChC,OAAI,CAAC,SACH,QAAO;AAGT,OAAImB,mCAAqB,OAAO,UAAU,SAAS,EAAE;AACnD,kBAAc;AACd;AAEA,QAAI,gBAAgB,eAAe,QAAQ;AACzC,oBAAe;AACf,YAAO;;cAEA,eAAe,EACxB,KAAIA,mCAAqB,OAAO,eAAe,IAAK,SAAS,EAAE;AAC7D,mBAAe;AACf,kBAAc;SAEd,gBAAe;AAInB,UAAO;;EAGT,QAAc;AACZ,kBAAe;AACf,iBAAc;;EAGhB,cAAsB;AACpB,UAAO;;EAEV"}