/** * @file Accessibility Enhancer * @description A11y improvements including focus management, screen reader * announcements, keyboard navigation, and ARIA utilities. * * Features: * - Focus management and trapping * - Screen reader announcements * - Keyboard navigation helpers * - ARIA attribute management * - Reduced motion support * - Color contrast utilities */ /** * Announcement priority */ export type AnnouncementPriority = 'polite' | 'assertive'; /** * Focus trap options */ export interface FocusTrapOptions { /** Element to trap focus within */ container: HTMLElement; /** Initial focus element */ initialFocus?: HTMLElement | string; /** Final focus element (when trap is released) */ returnFocus?: HTMLElement | boolean; /** Allow escape key to release trap */ escapeDeactivates?: boolean; /** Callback when escape is pressed */ onEscape?: () => void; /** Click outside behavior */ clickOutsideDeactivates?: boolean; /** Callback when clicking outside */ onClickOutside?: () => void; } /** * Focus trap controller */ export interface FocusTrapController { activate: () => void; deactivate: () => void; pause: () => void; resume: () => void; } /** * Roving tabindex options */ export interface RovingTabindexOptions { /** Container element */ container: HTMLElement; /** Selector for focusable items */ itemSelector: string; /** Orientation */ orientation: 'horizontal' | 'vertical' | 'both'; /** Loop navigation */ loop?: boolean; /** Initial focused index */ initialIndex?: number; /** Callback when item is focused */ onFocus?: (element: HTMLElement, index: number) => void; } /** * Skip link options */ export interface SkipLinkOptions { /** Target element ID */ targetId: string; /** Link text */ text?: string; /** Custom class name */ className?: string; } /** * Color contrast result */ export interface ContrastResult { ratio: number; aa: boolean; aaLarge: boolean; aaa: boolean; aaaLarge: boolean; } /** * Initialize screen reader announcer elements */ export declare function initAnnouncer(): void; /** * Announce a message to screen readers */ export declare function announce(message: string, priority?: AnnouncementPriority): void; /** * Announce a message assertively (interrupts current speech) */ export declare function announceAssertive(message: string): void; /** * Announce route change */ export declare function announceRouteChange(pageTitle: string): void; /** * Announce loading state */ export declare function announceLoading(isLoading: boolean, context?: string): void; /** * Announce form validation error */ export declare function announceError(message: string): void; /** * Announce success message */ export declare function announceSuccess(message: string): void; /** * Get all focusable elements within a container */ export declare function getFocusableElements(container: HTMLElement): HTMLElement[]; /** * Get the first focusable element within a container */ export declare function getFirstFocusable(container: HTMLElement): HTMLElement | null; /** * Get the last focusable element within a container */ export declare function getLastFocusable(container: HTMLElement): HTMLElement | null; /** * Focus the first focusable element in a container */ export declare function focusFirst(container: HTMLElement): boolean; /** * Focus the last focusable element in a container */ export declare function focusLast(container: HTMLElement): boolean; /** * Create a focus trap */ export declare function createFocusTrap(options: FocusTrapOptions): FocusTrapController; /** * Create a roving tabindex controller */ export declare function createRovingTabindex(options: RovingTabindexOptions): { init: () => void; destroy: () => void; setFocusedIndex: (index: number) => void; }; /** * Create a skip link element */ export declare function createSkipLink(options: SkipLinkOptions): HTMLAnchorElement; /** * Install default skip links */ export declare function installSkipLinks(): void; /** * Set ARIA expanded state */ export declare function setExpanded(element: HTMLElement, expanded: boolean, controlledId?: string): void; /** * Set ARIA pressed state (for toggle buttons) */ export declare function setPressed(element: HTMLElement, pressed: boolean): void; /** * Set ARIA selected state */ export declare function setSelected(element: HTMLElement, selected: boolean): void; /** * Set ARIA busy state */ export declare function setBusy(element: HTMLElement, busy: boolean): void; /** * Set ARIA disabled state */ export declare function setDisabled(element: HTMLElement, disabled: boolean): void; /** * Set ARIA hidden state */ export declare function setHidden(element: HTMLElement, hidden: boolean): void; export declare function generateAriaId(prefix?: string): string; /** * Check if user prefers reduced motion */ export declare function prefersReducedMotion(): boolean; /** * Subscribe to reduced motion preference changes */ export declare function onReducedMotionChange(callback: (prefersReduced: boolean) => void): () => void; /** * Get safe animation duration based on user preference */ export declare function getSafeAnimationDuration(normalDuration: number, reducedDuration?: number): number; /** * Calculate relative luminance of a color */ export declare function getLuminance(r: number, g: number, b: number): number; /** * Calculate contrast ratio between two colors */ export declare function getContrastRatio(color1: [number, number, number], color2: [number, number, number]): number; /** * Check if contrast meets WCAG requirements */ export declare function checkContrast(foreground: [number, number, number], background: [number, number, number]): ContrastResult; /** * Parse hex color to RGB */ export declare function hexToRgb(hex: string): [number, number, number] | null; export declare 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";