{"version":3,"file":"accessibility-enhancer.mjs","sources":["../../../src/lib/ux/accessibility-enhancer.ts"],"sourcesContent":["/**\n * @file Accessibility Enhancer\n * @description A11y improvements including focus management, screen reader\n * announcements, keyboard navigation, and ARIA utilities.\n *\n * Features:\n * - Focus management and trapping\n * - Screen reader announcements\n * - Keyboard navigation helpers\n * - ARIA attribute management\n * - Reduced motion support\n * - Color contrast utilities\n */\n\n/* eslint-disable @typescript-eslint/strict-boolean-expressions */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Announcement priority\n */\nexport type AnnouncementPriority = 'polite' | 'assertive';\n\n/**\n * Focus trap options\n */\nexport interface FocusTrapOptions {\n  /** Element to trap focus within */\n  container: HTMLElement;\n  /** Initial focus element */\n  initialFocus?: HTMLElement | string;\n  /** Final focus element (when trap is released) */\n  returnFocus?: HTMLElement | boolean;\n  /** Allow escape key to release trap */\n  escapeDeactivates?: boolean;\n  /** Callback when escape is pressed */\n  onEscape?: () => void;\n  /** Click outside behavior */\n  clickOutsideDeactivates?: boolean;\n  /** Callback when clicking outside */\n  onClickOutside?: () => void;\n}\n\n/**\n * Focus trap controller\n */\nexport interface FocusTrapController {\n  activate: () => void;\n  deactivate: () => void;\n  pause: () => void;\n  resume: () => void;\n}\n\n/**\n * Roving tabindex options\n */\nexport interface RovingTabindexOptions {\n  /** Container element */\n  container: HTMLElement;\n  /** Selector for focusable items */\n  itemSelector: string;\n  /** Orientation */\n  orientation: 'horizontal' | 'vertical' | 'both';\n  /** Loop navigation */\n  loop?: boolean;\n  /** Initial focused index */\n  initialIndex?: number;\n  /** Callback when item is focused */\n  onFocus?: (element: HTMLElement, index: number) => void;\n}\n\n/**\n * Skip link options\n */\nexport interface SkipLinkOptions {\n  /** Target element ID */\n  targetId: string;\n  /** Link text */\n  text?: string;\n  /** Custom class name */\n  className?: string;\n}\n\n/**\n * Color contrast result\n */\nexport interface ContrastResult {\n  ratio: number;\n  aa: boolean;\n  aaLarge: boolean;\n  aaa: boolean;\n  aaaLarge: boolean;\n}\n\n// ============================================================================\n// Screen Reader Announcements\n// ============================================================================\n\nlet announcerElement: HTMLElement | null = null;\nlet assertiveAnnouncerElement: HTMLElement | null = null;\n\n/**\n * Initialize screen reader announcer elements\n */\nexport function initAnnouncer(): void {\n  if (typeof document === 'undefined') return;\n\n  // Polite announcer\n  if (!announcerElement) {\n    announcerElement = document.createElement('div');\n    announcerElement.setAttribute('role', 'status');\n    announcerElement.setAttribute('aria-live', 'polite');\n    announcerElement.setAttribute('aria-atomic', 'true');\n    announcerElement.className = 'sr-only';\n    document.body.appendChild(announcerElement);\n  }\n\n  // Assertive announcer\n  if (!assertiveAnnouncerElement) {\n    assertiveAnnouncerElement = document.createElement('div');\n    assertiveAnnouncerElement.setAttribute('role', 'alert');\n    assertiveAnnouncerElement.setAttribute('aria-live', 'assertive');\n    assertiveAnnouncerElement.setAttribute('aria-atomic', 'true');\n    assertiveAnnouncerElement.className = 'sr-only';\n    document.body.appendChild(assertiveAnnouncerElement);\n  }\n}\n\n/**\n * Announce a message to screen readers\n */\nexport function announce(message: string, priority: AnnouncementPriority = 'polite'): void {\n  initAnnouncer();\n\n  const element = priority === 'assertive' ? assertiveAnnouncerElement : announcerElement;\n\n  if (!element) return;\n\n  // Clear and set after a brief delay to ensure announcement\n  element.textContent = '';\n  setTimeout(() => {\n    element.textContent = message;\n  }, 50);\n}\n\n/**\n * Announce a message assertively (interrupts current speech)\n */\nexport function announceAssertive(message: string): void {\n  announce(message, 'assertive');\n}\n\n/**\n * Announce route change\n */\nexport function announceRouteChange(pageTitle: string): void {\n  announce(`Navigated to ${pageTitle}`);\n}\n\n/**\n * Announce loading state\n */\nexport function announceLoading(isLoading: boolean, context?: string): void {\n  if (isLoading) {\n    announce(`Loading${context !== undefined && context !== '' ? ` ${context}` : ''}...`);\n  } else {\n    announce(`${context ?? 'Content'} loaded`);\n  }\n}\n\n/**\n * Announce form validation error\n */\nexport function announceError(message: string): void {\n  announceAssertive(`Error: ${message}`);\n}\n\n/**\n * Announce success message\n */\nexport function announceSuccess(message: string): void {\n  announce(message);\n}\n\n// ============================================================================\n// Focus Management\n// ============================================================================\n\nconst FOCUSABLE_SELECTOR = [\n  'a[href]',\n  'button:not([disabled])',\n  'input:not([disabled]):not([type=\"hidden\"])',\n  'select:not([disabled])',\n  'textarea:not([disabled])',\n  '[tabindex]:not([tabindex=\"-1\"])',\n  '[contenteditable=\"true\"]',\n].join(', ');\n\n/**\n * Get all focusable elements within a container\n */\nexport function getFocusableElements(container: HTMLElement): HTMLElement[] {\n  return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n    (el) => el.offsetParent !== null // Exclude hidden elements\n  );\n}\n\n/**\n * Get the first focusable element within a container\n */\nexport function getFirstFocusable(container: HTMLElement): HTMLElement | null {\n  const elements = getFocusableElements(container);\n  return elements[0] ?? null;\n}\n\n/**\n * Get the last focusable element within a container\n */\nexport function getLastFocusable(container: HTMLElement): HTMLElement | null {\n  const elements = getFocusableElements(container);\n  return elements[elements.length - 1] ?? null;\n}\n\n/**\n * Focus the first focusable element in a container\n */\nexport function focusFirst(container: HTMLElement): boolean {\n  const element = getFirstFocusable(container);\n  if (element) {\n    element.focus();\n    return true;\n  }\n  return false;\n}\n\n/**\n * Focus the last focusable element in a container\n */\nexport function focusLast(container: HTMLElement): boolean {\n  const element = getLastFocusable(container);\n  if (element) {\n    element.focus();\n    return true;\n  }\n  return false;\n}\n\n/**\n * Create a focus trap\n */\nexport function createFocusTrap(options: FocusTrapOptions): FocusTrapController {\n  const {\n    container,\n    initialFocus,\n    returnFocus = true,\n    escapeDeactivates = true,\n    onEscape,\n    clickOutsideDeactivates = false,\n    onClickOutside,\n  } = options;\n\n  let isActive = false;\n  let isPaused = false;\n  let previouslyFocused: HTMLElement | null = null;\n\n  const handleKeyDown = (event: KeyboardEvent): void => {\n    if (isPaused) return;\n\n    if (event.key === 'Tab') {\n      const focusables = getFocusableElements(container);\n      if (focusables.length === 0) return;\n\n      const [first] = focusables;\n      const last = focusables[focusables.length - 1];\n      const active = document.activeElement as HTMLElement;\n\n      if (event.shiftKey && active === first && last) {\n        event.preventDefault();\n        last.focus();\n      } else if (!event.shiftKey && active === last && first) {\n        event.preventDefault();\n        first.focus();\n      }\n    }\n\n    if (event.key === 'Escape' && escapeDeactivates) {\n      event.preventDefault();\n      onEscape?.();\n      deactivate();\n    }\n  };\n\n  const handleClickOutside = (event: MouseEvent): void => {\n    if (isPaused) return;\n    if (!container.contains(event.target as Node)) {\n      if (clickOutsideDeactivates) {\n        onClickOutside?.();\n        deactivate();\n      }\n    }\n  };\n\n  const activate = (): void => {\n    if (isActive) return;\n    isActive = true;\n\n    // Store previously focused element\n    previouslyFocused = document.activeElement as HTMLElement;\n\n    // Add event listeners\n    document.addEventListener('keydown', handleKeyDown);\n    if (clickOutsideDeactivates) {\n      document.addEventListener('click', handleClickOutside, true);\n    }\n\n    // Focus initial element\n    setTimeout(() => {\n      if (initialFocus) {\n        const element =\n          typeof initialFocus === 'string'\n            ? container.querySelector<HTMLElement>(initialFocus)\n            : initialFocus;\n        element?.focus();\n      } else {\n        focusFirst(container);\n      }\n    }, 0);\n  };\n\n  const deactivate = (): void => {\n    if (!isActive) return;\n    isActive = false;\n\n    // Remove event listeners\n    document.removeEventListener('keydown', handleKeyDown);\n    document.removeEventListener('click', handleClickOutside, true);\n\n    // Return focus\n    if (returnFocus && previouslyFocused) {\n      previouslyFocused?.focus();\n    }\n  };\n\n  const pause = (): void => {\n    isPaused = true;\n  };\n\n  const resume = (): void => {\n    isPaused = false;\n  };\n\n  return { activate, deactivate, pause, resume };\n}\n\n// ============================================================================\n// Roving Tabindex\n// ============================================================================\n\n/**\n * Create a roving tabindex controller\n */\nexport function createRovingTabindex(options: RovingTabindexOptions): {\n  init: () => void;\n  destroy: () => void;\n  setFocusedIndex: (index: number) => void;\n} {\n  const { container, itemSelector, orientation, loop = true, initialIndex = 0, onFocus } = options;\n\n  let currentIndex = initialIndex;\n  let items: HTMLElement[] = [];\n\n  const updateTabindices = (): void => {\n    items.forEach((item, index) => {\n      item.setAttribute('tabindex', index === currentIndex ? '0' : '-1');\n    });\n  };\n\n  const focusItem = (index: number): void => {\n    if (index < 0 || index >= items.length) return;\n    const item = items[index];\n    if (!item) return;\n    currentIndex = index;\n    updateTabindices();\n    item.focus();\n    onFocus?.(item, index);\n  };\n\n  const getNextIndex = (direction: number): number => {\n    let nextIndex = currentIndex + direction;\n\n    if (loop) {\n      if (nextIndex < 0) nextIndex = items.length - 1;\n      if (nextIndex >= items.length) nextIndex = 0;\n    } else {\n      nextIndex = Math.max(0, Math.min(items.length - 1, nextIndex));\n    }\n\n    return nextIndex;\n  };\n\n  const handleKeyDown = (event: KeyboardEvent): void => {\n    const isHorizontal = orientation === 'horizontal' || orientation === 'both';\n    const isVertical = orientation === 'vertical' || orientation === 'both';\n\n    let direction: number | null = null;\n\n    if (isHorizontal && event.key === 'ArrowRight') direction = 1;\n    if (isHorizontal && event.key === 'ArrowLeft') direction = -1;\n    if (isVertical && event.key === 'ArrowDown') direction = 1;\n    if (isVertical && event.key === 'ArrowUp') direction = -1;\n    if (event.key === 'Home') {\n      event.preventDefault();\n      focusItem(0);\n      return;\n    }\n    if (event.key === 'End') {\n      event.preventDefault();\n      focusItem(items.length - 1);\n      return;\n    }\n\n    if (direction !== null) {\n      event.preventDefault();\n      focusItem(getNextIndex(direction));\n    }\n  };\n\n  const init = (): void => {\n    items = Array.from(container.querySelectorAll<HTMLElement>(itemSelector));\n    updateTabindices();\n    container.addEventListener('keydown', handleKeyDown);\n  };\n\n  const destroy = (): void => {\n    container.removeEventListener('keydown', handleKeyDown);\n  };\n\n  const setFocusedIndex = (index: number): void => {\n    focusItem(index);\n  };\n\n  return { init, destroy, setFocusedIndex };\n}\n\n// ============================================================================\n// Skip Links\n// ============================================================================\n\n/**\n * Create a skip link element\n */\nexport function createSkipLink(options: SkipLinkOptions): HTMLAnchorElement {\n  const { targetId, text = 'Skip to main content', className = 'skip-link' } = options;\n\n  const link = document.createElement('a');\n  link.href = `#${targetId}`;\n  link.className = className;\n  link.textContent = text;\n\n  link.addEventListener('click', (event) => {\n    event.preventDefault();\n    const target = document.getElementById(targetId);\n    if (target) {\n      target.setAttribute('tabindex', '-1');\n      target.focus();\n      target.removeAttribute('tabindex');\n    }\n  });\n\n  return link;\n}\n\n/**\n * Install default skip links\n */\nexport function installSkipLinks(): void {\n  if (typeof document === 'undefined') return;\n\n  const skipLinkContainer = document.createElement('div');\n  skipLinkContainer.className = 'skip-links';\n\n  // Main content skip link\n  if (document.getElementById('main-content') || document.querySelector('main')) {\n    const mainLink = createSkipLink({\n      targetId: 'main-content',\n      text: 'Skip to main content',\n    });\n    skipLinkContainer.appendChild(mainLink);\n  }\n\n  // Navigation skip link\n  if (document.getElementById('main-nav') || document.querySelector('nav')) {\n    const navLink = createSkipLink({\n      targetId: 'main-nav',\n      text: 'Skip to navigation',\n    });\n    skipLinkContainer.appendChild(navLink);\n  }\n\n  if (skipLinkContainer.children.length > 0) {\n    document.body.insertBefore(skipLinkContainer, document.body.firstChild);\n  }\n}\n\n// ============================================================================\n// ARIA Utilities\n// ============================================================================\n\n/**\n * Set ARIA expanded state\n */\nexport function setExpanded(element: HTMLElement, expanded: boolean, controlledId?: string): void {\n  element.setAttribute('aria-expanded', String(expanded));\n  if (controlledId) {\n    element.setAttribute('aria-controls', controlledId);\n  }\n}\n\n/**\n * Set ARIA pressed state (for toggle buttons)\n */\nexport function setPressed(element: HTMLElement, pressed: boolean): void {\n  element.setAttribute('aria-pressed', String(pressed));\n}\n\n/**\n * Set ARIA selected state\n */\nexport function setSelected(element: HTMLElement, selected: boolean): void {\n  element.setAttribute('aria-selected', String(selected));\n}\n\n/**\n * Set ARIA busy state\n */\nexport function setBusy(element: HTMLElement, busy: boolean): void {\n  element.setAttribute('aria-busy', String(busy));\n}\n\n/**\n * Set ARIA disabled state\n */\nexport function setDisabled(element: HTMLElement, disabled: boolean): void {\n  element.setAttribute('aria-disabled', String(disabled));\n  if (disabled) {\n    element.setAttribute('tabindex', '-1');\n  } else {\n    element.removeAttribute('tabindex');\n  }\n}\n\n/**\n * Set ARIA hidden state\n */\nexport function setHidden(element: HTMLElement, hidden: boolean): void {\n  if (hidden) {\n    element.setAttribute('aria-hidden', 'true');\n    element.setAttribute('inert', '');\n  } else {\n    element.removeAttribute('aria-hidden');\n    element.removeAttribute('inert');\n  }\n}\n\n/**\n * Generate unique ID for ARIA relationships\n */\nlet ariaIdCounter = 0;\nexport function generateAriaId(prefix: string = 'aria'): string {\n  return `${prefix}-${++ariaIdCounter}`;\n}\n\n// ============================================================================\n// Reduced Motion\n// ============================================================================\n\n/**\n * Check if user prefers reduced motion\n */\nexport function prefersReducedMotion(): boolean {\n  if (typeof window === 'undefined') return false;\n  return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Subscribe to reduced motion preference changes\n */\nexport function onReducedMotionChange(callback: (prefersReduced: boolean) => void): () => void {\n  if (typeof window === 'undefined') return () => {};\n\n  const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\n\n  const handler = (event: MediaQueryListEvent): void => {\n    callback(event.matches);\n  };\n\n  mediaQuery.addEventListener('change', handler);\n  return () => mediaQuery.removeEventListener('change', handler);\n}\n\n/**\n * Get safe animation duration based on user preference\n */\nexport function getSafeAnimationDuration(\n  normalDuration: number,\n  reducedDuration: number = 0\n): number {\n  return prefersReducedMotion() ? reducedDuration : normalDuration;\n}\n\n// ============================================================================\n// Color Contrast\n// ============================================================================\n\n/**\n * Calculate relative luminance of a color\n */\nexport function getLuminance(r: number, g: number, b: number): number {\n  const [rs = 0, gs = 0, bs = 0] = [r, g, b].map((c) => {\n    const sRGB = c / 255;\n    return sRGB <= 0.03928 ? sRGB / 12.92 : Math.pow((sRGB + 0.055) / 1.055, 2.4);\n  });\n  return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;\n}\n\n/**\n * Calculate contrast ratio between two colors\n */\nexport function getContrastRatio(\n  color1: [number, number, number],\n  color2: [number, number, number]\n): number {\n  const l1 = getLuminance(...color1);\n  const l2 = getLuminance(...color2);\n  const lighter = Math.max(l1, l2);\n  const darker = Math.min(l1, l2);\n  return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Check if contrast meets WCAG requirements\n */\nexport function checkContrast(\n  foreground: [number, number, number],\n  background: [number, number, number]\n): ContrastResult {\n  const ratio = getContrastRatio(foreground, background);\n\n  return {\n    ratio,\n    aa: ratio >= 4.5,\n    aaLarge: ratio >= 3,\n    aaa: ratio >= 7,\n    aaaLarge: ratio >= 4.5,\n  };\n}\n\n/**\n * Parse hex color to RGB\n */\nexport function hexToRgb(hex: string): [number, number, number] | null {\n  const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n  return result?.[1] && result[2] && result[3]\n    ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]\n    : null;\n}\n\n// ============================================================================\n// CSS Export\n// ============================================================================\n\nexport const accessibilityStyles = `\n  .sr-only {\n    position: absolute;\n    width: 1px;\n    height: 1px;\n    padding: 0;\n    margin: -1px;\n    overflow: hidden;\n    clip: rect(0, 0, 0, 0);\n    white-space: nowrap;\n    border: 0;\n  }\n\n  .skip-link {\n    position: absolute;\n    top: -40px;\n    left: 0;\n    background: #000;\n    color: #fff;\n    padding: 8px 16px;\n    z-index: 10000;\n    text-decoration: none;\n  }\n\n  .skip-link:focus {\n    top: 0;\n  }\n\n  .skip-links {\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: 10000;\n  }\n\n  /* Visible focus styles */\n  :focus-visible {\n    outline: 2px solid #3b82f6;\n    outline-offset: 2px;\n  }\n\n  /* Reduced motion */\n  @media (prefers-reduced-motion: reduce) {\n    *,\n    *::before,\n    *::after {\n      animation-duration: 0.01ms !important;\n      animation-iteration-count: 1 !important;\n      transition-duration: 0.01ms !important;\n      scroll-behavior: auto !important;\n    }\n  }\n`;\n"],"names":["announcerElement","assertiveAnnouncerElement","initAnnouncer","announce","message","priority","element","announceAssertive","announceRouteChange","pageTitle","announceLoading","isLoading","context","announceError","announceSuccess","FOCUSABLE_SELECTOR","getFocusableElements","container","el","getFirstFocusable","getLastFocusable","elements","focusFirst","focusLast","createFocusTrap","options","initialFocus","returnFocus","escapeDeactivates","onEscape","clickOutsideDeactivates","onClickOutside","isActive","isPaused","previouslyFocused","handleKeyDown","event","focusables","first","last","active","deactivate","handleClickOutside","activate","createRovingTabindex","itemSelector","orientation","loop","initialIndex","onFocus","currentIndex","items","updateTabindices","item","index","focusItem","getNextIndex","direction","nextIndex","isHorizontal","isVertical","createSkipLink","targetId","text","className","link","target","installSkipLinks","skipLinkContainer","mainLink","navLink","setExpanded","expanded","controlledId","setPressed","pressed","setSelected","selected","setBusy","busy","setDisabled","disabled","setHidden","hidden","ariaIdCounter","generateAriaId","prefix","prefersReducedMotion","onReducedMotionChange","callback","mediaQuery","handler","getSafeAnimationDuration","normalDuration","reducedDuration","getLuminance","r","g","b","rs","gs","bs","c","sRGB","getContrastRatio","color1","color2","l1","l2","lighter","darker","checkContrast","foreground","background","ratio","hexToRgb","hex","result","accessibilityStyles"],"mappings":"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"}