{"version":3,"file":"useMemoryPressure.mjs","sources":["../../../../src/lib/performance/hooks/useMemoryPressure.ts"],"sourcesContent":["/**\n * @file useMemoryPressure Hook\n * @description React hook for monitoring JavaScript heap memory usage and pressure.\n *\n * Provides components with awareness of memory conditions, enabling\n * adaptive behavior to prevent memory-related performance degradation.\n *\n * Note: The Memory API (performance.memory) is only available in Chrome/Chromium browsers.\n * This hook gracefully degrades on unsupported browsers.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const {\n *     pressure,\n *     usagePercent,\n *     isUnderPressure,\n *     shouldReduceMemory\n *   } = useMemoryPressure({\n *     onPressureChange: (pressure) => {\n *       if (pressure === 'critical') {\n *         clearCaches();\n *       }\n *     }\n *   });\n *\n *   // Reduce memory usage when under pressure\n *   if (shouldReduceMemory) {\n *     return <LiteVersion />;\n *   }\n *\n *   return <FullVersion />;\n * }\n * ```\n */\n\nimport { useState, useEffect, useCallback, useRef, useMemo } from 'react';\nimport { MEMORY_CONFIG, formatBytes } from '../../../config/performance.config';\nimport { isMemoryApiSupported, getPerformanceMemory } from '../utils/memory';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Memory pressure level\n */\nexport type MemoryPressureLevel = 'normal' | 'warning' | 'critical';\n\n/**\n * Memory snapshot\n */\nexport interface MemorySnapshot {\n  /** Used JS heap size in bytes */\n  readonly usedJSHeapSize: number;\n  /** Total JS heap size in bytes */\n  readonly totalJSHeapSize: number;\n  /** JS heap size limit in bytes */\n  readonly jsHeapSizeLimit: number;\n  /** Usage as percentage (0-100) */\n  readonly usagePercent: number;\n  /** Current pressure level */\n  readonly pressure: MemoryPressureLevel;\n  /** Timestamp of snapshot */\n  readonly timestamp: number;\n}\n\n/**\n * Memory trend data\n */\nexport interface MemoryTrend {\n  /** Direction of memory usage */\n  readonly direction: 'increasing' | 'stable' | 'decreasing';\n  /** Rate of change (bytes per second) */\n  readonly rateOfChange: number;\n  /** Estimated time until critical (ms) or null if not increasing */\n  readonly timeUntilCritical: number | null;\n}\n\n/**\n * Hook options\n */\nexport interface UseMemoryPressureOptions {\n  /** Warning threshold (0-1) */\n  readonly warningThreshold?: number;\n  /** Critical threshold (0-1) */\n  readonly criticalThreshold?: number;\n  /** Polling interval (ms) */\n  readonly pollingInterval?: number;\n  /** Callback on pressure change */\n  readonly onPressureChange?: (pressure: MemoryPressureLevel, snapshot: MemorySnapshot) => void;\n  /** Callback on critical pressure */\n  readonly onCritical?: (snapshot: MemorySnapshot) => void;\n  /** Enable automatic cleanup on critical */\n  readonly autoCleanup?: boolean;\n  /** Custom cleanup function */\n  readonly cleanupFn?: () => void;\n  /** Enable debug logging */\n  readonly debug?: boolean;\n}\n\n/**\n * Hook return value\n */\nexport interface UseMemoryPressureReturn {\n  /** Current memory snapshot */\n  readonly snapshot: MemorySnapshot | null;\n  /** Current pressure level */\n  readonly pressure: MemoryPressureLevel;\n  /** Usage percentage (0-100) */\n  readonly usagePercent: number;\n  /** Whether under any pressure (warning or critical) */\n  readonly isUnderPressure: boolean;\n  /** Whether should reduce memory usage */\n  readonly shouldReduceMemory: boolean;\n  /** Memory trend */\n  readonly trend: MemoryTrend | null;\n  /** Whether Memory API is supported */\n  readonly isSupported: boolean;\n  /** Force a memory snapshot */\n  readonly refresh: () => void;\n  /** Request garbage collection (if available) */\n  readonly requestGC: () => void;\n  /** Get memory history */\n  readonly getHistory: () => MemorySnapshot[];\n  /** Format bytes for display */\n  readonly formatBytes: (bytes: number) => string;\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for memory pressure monitoring\n */\nexport function useMemoryPressure(\n  options: UseMemoryPressureOptions = {}\n): UseMemoryPressureReturn {\n  const {\n    warningThreshold = MEMORY_CONFIG.warningThreshold,\n    criticalThreshold = MEMORY_CONFIG.criticalThreshold,\n    pollingInterval = MEMORY_CONFIG.pollingInterval,\n    onPressureChange,\n    onCritical,\n    autoCleanup = MEMORY_CONFIG.autoCleanup,\n    cleanupFn,\n    debug = false,\n  } = options;\n\n  // State\n  const [snapshot, setSnapshot] = useState<MemorySnapshot | null>(null);\n  const [history, setHistory] = useState<MemorySnapshot[]>([]);\n  const [isSupported] = useState(isMemoryApiSupported);\n\n  // Refs for callbacks\n  const lastPressureRef = useRef<MemoryPressureLevel>('normal');\n  const callbacksRef = useRef({ onPressureChange, onCritical, cleanupFn });\n\n  // Update callbacks ref\n  useEffect(() => {\n    callbacksRef.current = { onPressureChange, onCritical, cleanupFn };\n  }, [onPressureChange, onCritical, cleanupFn]);\n\n  // Calculate pressure level\n  const calculatePressure = useCallback(\n    (usagePercent: number): MemoryPressureLevel => {\n      const usage = usagePercent / 100;\n      if (usage >= criticalThreshold) return 'critical';\n      if (usage >= warningThreshold) return 'warning';\n      return 'normal';\n    },\n    [warningThreshold, criticalThreshold]\n  );\n\n  // Take memory snapshot\n  const takeSnapshot = useCallback((): MemorySnapshot | null => {\n    const memory = getPerformanceMemory();\n    if (!memory) return null;\n\n    const usagePercent = (memory.usedJSHeapSize / memory.jsHeapSizeLimit) * 100;\n    const pressure = calculatePressure(usagePercent);\n\n    return {\n      usedJSHeapSize: memory.usedJSHeapSize,\n      totalJSHeapSize: memory.totalJSHeapSize,\n      jsHeapSizeLimit: memory.jsHeapSizeLimit,\n      usagePercent,\n      pressure,\n      timestamp: Date.now(),\n    };\n  }, [calculatePressure]);\n\n  // Request garbage collection (Chrome DevTools only)\n  const requestGC = useCallback((): void => {\n    if (typeof globalThis !== 'undefined' && 'gc' in globalThis) {\n      try {\n        const globalWithGC = globalThis as typeof globalThis & { gc: () => void };\n        globalWithGC.gc();\n        if (debug) {\n          console.info('[useMemoryPressure] GC requested');\n        }\n      } catch {\n        if (debug) {\n          console.info('[useMemoryPressure] GC not available');\n        }\n      }\n    }\n  }, [debug]);\n\n  // Perform cleanup\n  const performCleanup = useCallback((): void => {\n    if (debug) {\n      console.info('[useMemoryPressure] Performing cleanup');\n    }\n\n    // Clear caches if available\n    if ('caches' in globalThis) {\n      // Don't actually clear caches, just log\n      if (debug) {\n        console.info('[useMemoryPressure] Cache clearing would be performed here');\n      }\n    }\n\n    // Call custom cleanup\n    callbacksRef.current.cleanupFn?.();\n\n    // Request GC\n    requestGC();\n  }, [debug, requestGC]);\n\n  // Polling effect\n  useEffect(() => {\n    if (!isSupported) return;\n\n    const poll = (): void => {\n      const newSnapshot = takeSnapshot();\n      if (!newSnapshot) return;\n\n      setSnapshot(newSnapshot);\n      setHistory((prev) => {\n        const updated = [...prev, newSnapshot];\n        // Keep last 100 snapshots\n        return updated.slice(-100);\n      });\n\n      // Check for pressure change\n      if (newSnapshot.pressure !== lastPressureRef.current) {\n        if (debug) {\n          console.info(\n            `[useMemoryPressure] Pressure changed: ${lastPressureRef.current} -> ${newSnapshot.pressure}`\n          );\n        }\n\n        callbacksRef.current.onPressureChange?.(newSnapshot.pressure, newSnapshot);\n\n        // Handle critical\n        if (newSnapshot.pressure === 'critical') {\n          callbacksRef.current.onCritical?.(newSnapshot);\n\n          if (autoCleanup) {\n            performCleanup();\n          }\n        }\n\n        lastPressureRef.current = newSnapshot.pressure;\n      }\n    };\n\n    // Initial poll\n    poll();\n\n    // Set up interval\n    const intervalId = setInterval(poll, pollingInterval);\n\n    return () => clearInterval(intervalId);\n  }, [isSupported, pollingInterval, takeSnapshot, autoCleanup, performCleanup, debug]);\n\n  // Calculate trend\n  const trend = useMemo<MemoryTrend | null>(() => {\n    if (history.length < 2) return null;\n\n    const recentHistory = history.slice(-10);\n    const [oldestSnapshot] = recentHistory;\n    const newestSnapshot = recentHistory[recentHistory.length - 1];\n\n    if (!oldestSnapshot || !newestSnapshot) return null;\n\n    const timeDiff = newestSnapshot.timestamp - oldestSnapshot.timestamp;\n    if (timeDiff === 0) return null;\n\n    const byteDiff = newestSnapshot.usedJSHeapSize - oldestSnapshot.usedJSHeapSize;\n    const rateOfChange = (byteDiff / timeDiff) * 1000; // bytes per second\n\n    let direction: 'increasing' | 'stable' | 'decreasing';\n    if (Math.abs(rateOfChange) < 1024 * 10) {\n      // Less than 10KB/s change\n      direction = 'stable';\n    } else if (rateOfChange > 0) {\n      direction = 'increasing';\n    } else {\n      direction = 'decreasing';\n    }\n\n    // Calculate time until critical\n    let timeUntilCritical: number | null = null;\n    if (direction === 'increasing' && newestSnapshot.pressure !== 'critical') {\n      const criticalBytes = newestSnapshot.jsHeapSizeLimit * criticalThreshold;\n      const bytesToCritical = criticalBytes - newestSnapshot.usedJSHeapSize;\n      if (bytesToCritical > 0 && rateOfChange > 0) {\n        timeUntilCritical = (bytesToCritical / rateOfChange) * 1000;\n      }\n    }\n\n    return {\n      direction,\n      rateOfChange,\n      timeUntilCritical,\n    };\n  }, [history, criticalThreshold]);\n\n  // Refresh (manual snapshot)\n  const refresh = useCallback((): void => {\n    const newSnapshot = takeSnapshot();\n    if (newSnapshot) {\n      setSnapshot(newSnapshot);\n    }\n  }, [takeSnapshot]);\n\n  // Get history\n  const getHistory = useCallback((): MemorySnapshot[] => {\n    return [...history];\n  }, [history]);\n\n  // Derived values\n  const pressure = snapshot?.pressure ?? 'normal';\n  const usagePercent = snapshot?.usagePercent ?? 0;\n  const isUnderPressure = pressure !== 'normal';\n  const shouldReduceMemory = pressure === 'critical' || (pressure === 'warning' && (trend?.direction === 'increasing'));\n\n  return {\n    snapshot,\n    pressure,\n    usagePercent,\n    isUnderPressure,\n    shouldReduceMemory,\n    trend,\n    isSupported,\n    refresh,\n    requestGC,\n    getHistory,\n    formatBytes,\n  };\n}\n\n// ============================================================================\n// Utility Hooks\n// ============================================================================\n\n/**\n * Hook that triggers cleanup when memory pressure is detected\n */\nexport function useMemoryCleanup(\n  cleanupFn: () => void,\n  options: { threshold?: MemoryPressureLevel } = {}\n): void {\n  const { threshold = 'warning' } = options;\n  const cleanupRef = useRef(cleanupFn);\n\n  useEffect(() => {\n    cleanupRef.current = cleanupFn;\n  }, [cleanupFn]);\n\n  const { pressure: _pressure } = useMemoryPressure({\n    onPressureChange: (newPressure) => {\n      if (\n        (threshold === 'warning' && newPressure !== 'normal') ||\n        (threshold === 'critical' && newPressure === 'critical')\n      ) {\n        cleanupRef.current();\n      }\n    },\n  });\n}\n\n/**\n * Hook that provides memory-aware caching\n */\nexport function useMemoryAwareCache<T>(\n  maxSize: number = 100\n): {\n  get: (key: string) => T | undefined;\n  set: (key: string, value: T) => void;\n  clear: () => void;\n  size: number;\n} {\n  const cacheRef = useRef<Map<string, T>>(new Map());\n  const [size, setSize] = useState(0);\n\n  const { shouldReduceMemory } = useMemoryPressure();\n\n  // Reduce cache size when under pressure\n  useEffect(() => {\n    if (shouldReduceMemory && cacheRef.current.size > 0) {\n      // Keep only half the items\n      const entries = Array.from(cacheRef.current.entries());\n      const toKeep = entries.slice(-Math.floor(entries.length / 2));\n      cacheRef.current = new Map(toKeep);\n      setSize(cacheRef.current.size);\n    }\n  }, [shouldReduceMemory]);\n\n  const get = useCallback((key: string): T | undefined => {\n    return cacheRef.current.get(key);\n  }, []);\n\n  const set = useCallback(\n    (key: string, value: T): void => {\n      // Evict oldest if at capacity\n      if (cacheRef.current.size >= maxSize) {\n        const firstKey = cacheRef.current.keys().next().value;\n        if (firstKey !== undefined && firstKey !== null) cacheRef.current.delete(firstKey);\n      }\n\n      cacheRef.current.set(key, value);\n      setSize(cacheRef.current.size);\n    },\n    [maxSize]\n  );\n\n  const clear = useCallback((): void => {\n    cacheRef.current.clear();\n    setSize(0);\n  }, []);\n\n  return { get, set, clear, size };\n}\n\n/**\n * Hook that monitors component memory impact\n */\nexport function useComponentMemoryImpact(): {\n  mountSize: number | null;\n  currentSize: number | null;\n  impact: number | null;\n} {\n  const [mountSize, setMountSize] = useState<number | null>(null);\n  const [currentSize, setCurrentSize] = useState<number | null>(null);\n\n  const { snapshot } = useMemoryPressure();\n\n  // Capture mount size\n  useEffect(() => {\n    if (snapshot !== null && mountSize === null) {\n      // eslint-disable-next-line react-hooks/set-state-in-effect\n      setMountSize(snapshot.usedJSHeapSize);\n    }\n  }, [snapshot, mountSize]);\n\n  // Update current size\n  useEffect(() => {\n    if (snapshot !== null) {\n      // eslint-disable-next-line react-hooks/set-state-in-effect\n      setCurrentSize(snapshot.usedJSHeapSize);\n    }\n  }, [snapshot]);\n\n  const impact = useMemo(() => {\n    if (mountSize === null || currentSize === null) return null;\n    return currentSize - mountSize;\n  }, [currentSize, mountSize]);\n\n  return {\n    mountSize,\n    currentSize,\n    impact,\n  };\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n// Types are already exported at their declaration sites\n"],"names":["useMemoryPressure","options","warningThreshold","MEMORY_CONFIG","criticalThreshold","pollingInterval","onPressureChange","onCritical","autoCleanup","cleanupFn","debug","snapshot","setSnapshot","useState","history","setHistory","isSupported","isMemoryApiSupported","lastPressureRef","useRef","callbacksRef","useEffect","calculatePressure","useCallback","usagePercent","usage","takeSnapshot","memory","getPerformanceMemory","pressure","requestGC","performCleanup","poll","newSnapshot","prev","intervalId","trend","useMemo","recentHistory","oldestSnapshot","newestSnapshot","timeDiff","rateOfChange","direction","timeUntilCritical","bytesToCritical","refresh","getHistory","isUnderPressure","shouldReduceMemory","formatBytes","useMemoryCleanup","threshold","cleanupRef","_pressure","newPressure","useMemoryAwareCache","maxSize","cacheRef","size","setSize","entries","toKeep","get","key","set","value","firstKey","clear","useComponentMemoryImpact","mountSize","setMountSize","currentSize","setCurrentSize","impact"],"mappings":";;;AAwIO,SAASA,EACdC,IAAoC,IACX;AACzB,QAAM;AAAA,IACJ,kBAAAC,IAAmBC,EAAc;AAAA,IACjC,mBAAAC,IAAoBD,EAAc;AAAA,IAClC,iBAAAE,IAAkBF,EAAc;AAAA,IAChC,kBAAAG;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC,IAAcL,EAAc;AAAA,IAC5B,WAAAM;AAAA,IACA,OAAAC,IAAQ;AAAA,EAAA,IACNT,GAGE,CAACU,GAAUC,CAAW,IAAIC,EAAgC,IAAI,GAC9D,CAACC,GAASC,CAAU,IAAIF,EAA2B,CAAA,CAAE,GACrD,CAACG,CAAW,IAAIH,EAASI,CAAoB,GAG7CC,IAAkBC,EAA4B,QAAQ,GACtDC,IAAeD,EAAO,EAAE,kBAAAb,GAAkB,YAAAC,GAAY,WAAAE,GAAW;AAGvE,EAAAY,EAAU,MAAM;AACd,IAAAD,EAAa,UAAU,EAAE,kBAAAd,GAAkB,YAAAC,GAAY,WAAAE,EAAA;AAAA,EACzD,GAAG,CAACH,GAAkBC,GAAYE,CAAS,CAAC;AAG5C,QAAMa,IAAoBC;AAAA,IACxB,CAACC,MAA8C;AAC7C,YAAMC,IAAQD,IAAe;AAC7B,aAAIC,KAASrB,IAA0B,aACnCqB,KAASvB,IAAyB,YAC/B;AAAA,IACT;AAAA,IACA,CAACA,GAAkBE,CAAiB;AAAA,EAAA,GAIhCsB,IAAeH,EAAY,MAA6B;AAC5D,UAAMI,IAASC,EAAA;AACf,QAAI,CAACD,EAAQ,QAAO;AAEpB,UAAMH,IAAgBG,EAAO,iBAAiBA,EAAO,kBAAmB,KAClEE,IAAWP,EAAkBE,CAAY;AAE/C,WAAO;AAAA,MACL,gBAAgBG,EAAO;AAAA,MACvB,iBAAiBA,EAAO;AAAA,MACxB,iBAAiBA,EAAO;AAAA,MACxB,cAAAH;AAAAA,MACA,UAAAK;AAAAA,MACA,WAAW,KAAK,IAAA;AAAA,IAAI;AAAA,EAExB,GAAG,CAACP,CAAiB,CAAC,GAGhBQ,IAAYP,EAAY,MAAY;AACxC,QAAI,OAAO,aAAe,OAAe,QAAQ;AAC/C,UAAI;AAEF,QADqB,WACR,GAAA,GACTb,KACF,QAAQ,KAAK,kCAAkC;AAAA,MAEnD,QAAQ;AACN,QAAIA,KACF,QAAQ,KAAK,sCAAsC;AAAA,MAEvD;AAAA,EAEJ,GAAG,CAACA,CAAK,CAAC,GAGJqB,IAAiBR,EAAY,MAAY;AAC7C,IAAIb,KACF,QAAQ,KAAK,wCAAwC,GAInD,YAAY,cAEVA,KACF,QAAQ,KAAK,4DAA4D,GAK7EU,EAAa,QAAQ,YAAA,GAGrBU,EAAA;AAAA,EACF,GAAG,CAACpB,GAAOoB,CAAS,CAAC;AAGrB,EAAAT,EAAU,MAAM;AACd,QAAI,CAACL,EAAa;AAElB,UAAMgB,IAAO,MAAY;AACvB,YAAMC,IAAcP,EAAA;AACpB,MAAKO,MAELrB,EAAYqB,CAAW,GACvBlB,EAAW,CAACmB,MACM,CAAC,GAAGA,GAAMD,CAAW,EAEtB,MAAM,IAAI,CAC1B,GAGGA,EAAY,aAAaf,EAAgB,YACvCR,KACF,QAAQ;AAAA,QACN,yCAAyCQ,EAAgB,OAAO,OAAOe,EAAY,QAAQ;AAAA,MAAA,GAI/Fb,EAAa,QAAQ,mBAAmBa,EAAY,UAAUA,CAAW,GAGrEA,EAAY,aAAa,eAC3Bb,EAAa,QAAQ,aAAaa,CAAW,GAEzCzB,KACFuB,EAAA,IAIJb,EAAgB,UAAUe,EAAY;AAAA,IAE1C;AAGA,IAAAD,EAAA;AAGA,UAAMG,IAAa,YAAYH,GAAM3B,CAAe;AAEpD,WAAO,MAAM,cAAc8B,CAAU;AAAA,EACvC,GAAG,CAACnB,GAAaX,GAAiBqB,GAAclB,GAAauB,GAAgBrB,CAAK,CAAC;AAGnF,QAAM0B,IAAQC,EAA4B,MAAM;AAC9C,QAAIvB,EAAQ,SAAS,EAAG,QAAO;AAE/B,UAAMwB,IAAgBxB,EAAQ,MAAM,GAAG,GACjC,CAACyB,CAAc,IAAID,GACnBE,IAAiBF,EAAcA,EAAc,SAAS,CAAC;AAE7D,QAAI,CAACC,KAAkB,CAACC,EAAgB,QAAO;AAE/C,UAAMC,IAAWD,EAAe,YAAYD,EAAe;AAC3D,QAAIE,MAAa,EAAG,QAAO;AAG3B,UAAMC,KADWF,EAAe,iBAAiBD,EAAe,kBAC/BE,IAAY;AAE7C,QAAIE;AACJ,IAAI,KAAK,IAAID,CAAY,IAAI,OAAO,KAElCC,IAAY,WACHD,IAAe,IACxBC,IAAY,eAEZA,IAAY;AAId,QAAIC,IAAmC;AACvC,QAAID,MAAc,gBAAgBH,EAAe,aAAa,YAAY;AAExE,YAAMK,IADgBL,EAAe,kBAAkBpC,IACfoC,EAAe;AACvD,MAAIK,IAAkB,KAAKH,IAAe,MACxCE,IAAqBC,IAAkBH,IAAgB;AAAA,IAE3D;AAEA,WAAO;AAAA,MACL,WAAAC;AAAA,MACA,cAAAD;AAAA,MACA,mBAAAE;AAAA,IAAA;AAAA,EAEJ,GAAG,CAAC9B,GAASV,CAAiB,CAAC,GAGzB0C,IAAUvB,EAAY,MAAY;AACtC,UAAMU,IAAcP,EAAA;AACpB,IAAIO,KACFrB,EAAYqB,CAAW;AAAA,EAE3B,GAAG,CAACP,CAAY,CAAC,GAGXqB,IAAaxB,EAAY,MACtB,CAAC,GAAGT,CAAO,GACjB,CAACA,CAAO,CAAC,GAGNe,IAAWlB,GAAU,YAAY,UACjCa,IAAeb,GAAU,gBAAgB,GACzCqC,IAAkBnB,MAAa,UAC/BoB,IAAqBpB,MAAa,cAAeA,MAAa,aAAcO,GAAO,cAAc;AAEvG,SAAO;AAAA,IACL,UAAAzB;AAAA,IACA,UAAAkB;AAAA,IACA,cAAAL;AAAA,IACA,iBAAAwB;AAAA,IACA,oBAAAC;AAAA,IACA,OAAAb;AAAA,IACA,aAAApB;AAAA,IACA,SAAA8B;AAAA,IACA,WAAAhB;AAAA,IACA,YAAAiB;AAAA,IACA,aAAAG;AAAA,EAAA;AAEJ;AASO,SAASC,EACd1C,GACAR,IAA+C,IACzC;AACN,QAAM,EAAE,WAAAmD,IAAY,UAAA,IAAcnD,GAC5BoD,IAAalC,EAAOV,CAAS;AAEnC,EAAAY,EAAU,MAAM;AACd,IAAAgC,EAAW,UAAU5C;AAAA,EACvB,GAAG,CAACA,CAAS,CAAC;AAEd,QAAM,EAAE,UAAU6C,EAAA,IAActD,EAAkB;AAAA,IAChD,kBAAkB,CAACuD,MAAgB;AACjC,OACGH,MAAc,aAAaG,MAAgB,YAC3CH,MAAc,cAAcG,MAAgB,eAE7CF,EAAW,QAAA;AAAA,IAEf;AAAA,EAAA,CACD;AACH;AAKO,SAASG,EACdC,IAAkB,KAMlB;AACA,QAAMC,IAAWvC,EAAuB,oBAAI,KAAK,GAC3C,CAACwC,GAAMC,CAAO,IAAI/C,EAAS,CAAC,GAE5B,EAAE,oBAAAoC,EAAA,IAAuBjD,EAAA;AAG/B,EAAAqB,EAAU,MAAM;AACd,QAAI4B,KAAsBS,EAAS,QAAQ,OAAO,GAAG;AAEnD,YAAMG,IAAU,MAAM,KAAKH,EAAS,QAAQ,SAAS,GAC/CI,IAASD,EAAQ,MAAM,CAAC,KAAK,MAAMA,EAAQ,SAAS,CAAC,CAAC;AAC5D,MAAAH,EAAS,UAAU,IAAI,IAAII,CAAM,GACjCF,EAAQF,EAAS,QAAQ,IAAI;AAAA,IAC/B;AAAA,EACF,GAAG,CAACT,CAAkB,CAAC;AAEvB,QAAMc,IAAMxC,EAAY,CAACyC,MAChBN,EAAS,QAAQ,IAAIM,CAAG,GAC9B,CAAA,CAAE,GAECC,IAAM1C;AAAA,IACV,CAACyC,GAAaE,MAAmB;AAE/B,UAAIR,EAAS,QAAQ,QAAQD,GAAS;AACpC,cAAMU,IAAWT,EAAS,QAAQ,KAAA,EAAO,OAAO;AAChD,QAA8BS,KAAa,QAAMT,EAAS,QAAQ,OAAOS,CAAQ;AAAA,MACnF;AAEA,MAAAT,EAAS,QAAQ,IAAIM,GAAKE,CAAK,GAC/BN,EAAQF,EAAS,QAAQ,IAAI;AAAA,IAC/B;AAAA,IACA,CAACD,CAAO;AAAA,EAAA,GAGJW,IAAQ7C,EAAY,MAAY;AACpC,IAAAmC,EAAS,QAAQ,MAAA,GACjBE,EAAQ,CAAC;AAAA,EACX,GAAG,CAAA,CAAE;AAEL,SAAO,EAAE,KAAAG,GAAK,KAAAE,GAAK,OAAAG,GAAO,MAAAT,EAAA;AAC5B;AAKO,SAASU,IAId;AACA,QAAM,CAACC,GAAWC,CAAY,IAAI1D,EAAwB,IAAI,GACxD,CAAC2D,GAAaC,CAAc,IAAI5D,EAAwB,IAAI,GAE5D,EAAE,UAAAF,EAAA,IAAaX,EAAA;AAGrB,EAAAqB,EAAU,MAAM;AACd,IAAIV,MAAa,QAAQ2D,MAAc,QAErCC,EAAa5D,EAAS,cAAc;AAAA,EAExC,GAAG,CAACA,GAAU2D,CAAS,CAAC,GAGxBjD,EAAU,MAAM;AACd,IAAIV,MAAa,QAEf8D,EAAe9D,EAAS,cAAc;AAAA,EAE1C,GAAG,CAACA,CAAQ,CAAC;AAEb,QAAM+D,IAASrC,EAAQ,MACjBiC,MAAc,QAAQE,MAAgB,OAAa,OAChDA,IAAcF,GACpB,CAACE,GAAaF,CAAS,CAAC;AAE3B,SAAO;AAAA,IACL,WAAAA;AAAA,IACA,aAAAE;AAAA,IACA,QAAAE;AAAA,EAAA;AAEJ;"}