UNPKG

@neuroequality/neuroadapt-core

Version:

Core sensory, cognitive, and preference management for NeuroAdapt SDK

190 lines (181 loc) 5.14 kB
const DEFAULT_OPTIONS = { color: "#005fcc", width: "3px", offset: "2px", style: "solid", borderRadius: "3px", duration: "0.15s", targetElement: document.documentElement, className: "neuro-focus-ring" }; class AccessibleFocusRing { constructor(options = {}) { this.isApplied = false; this.options = { ...DEFAULT_OPTIONS, ...options }; } /** * Apply the accessible focus ring styles to the target element */ apply() { if (this.isApplied) { return; } this.createStyleElement(); this.isApplied = true; } /** * Remove the accessible focus ring styles */ remove() { var _a; if (!this.isApplied) { return; } if ((_a = this.styleElement) == null ? void 0 : _a.parentNode) { this.styleElement.parentNode.removeChild(this.styleElement); } this.styleElement = void 0; this.isApplied = false; } /** * Update the focus ring configuration */ updateOptions(newOptions) { Object.assign(this.options, newOptions); if (this.isApplied) { this.remove(); this.apply(); } } /** * Check if focus ring is currently applied */ isActive() { return this.isApplied; } /** * Get current focus ring options */ getOptions() { return { ...this.options }; } createStyleElement() { this.styleElement = document.createElement("style"); this.styleElement.id = `${this.options.className}-styles`; this.styleElement.textContent = this.generateCSS(); document.head.appendChild(this.styleElement); } generateCSS() { const { color, width, offset, style, borderRadius, duration, className } = this.options; return ` /* Accessible Focus Ring Styles */ .${className} *:focus { outline: ${width} ${style} ${color} !important; outline-offset: ${offset} !important; border-radius: ${borderRadius} !important; transition: outline ${duration} ease-in-out !important; box-shadow: 0 0 0 ${offset} ${color}40 !important; } /* Enhanced focus for interactive elements */ .${className} button:focus, .${className} input:focus, .${className} textarea:focus, .${className} select:focus, .${className} a:focus, .${className} [tabindex]:focus { outline-width: ${width} !important; outline-style: ${style} !important; outline-color: ${color} !important; outline-offset: ${offset} !important; box-shadow: 0 0 0 ${offset} ${color}40, 0 0 0 calc(${offset} + ${width}) ${color}20 !important; } /* Focus within for containers */ .${className} [role="button"]:focus-within, .${className} [role="tab"]:focus-within, .${className} [role="menuitem"]:focus-within { outline: ${width} ${style} ${color} !important; outline-offset: ${offset} !important; } /* Skip link focus enhancement */ .${className} .skip-link:focus { position: absolute !important; top: 10px !important; left: 10px !important; z-index: 9999 !important; padding: 8px 16px !important; background: ${color} !important; color: white !important; text-decoration: none !important; border-radius: ${borderRadius} !important; font-weight: bold !important; } /* High contrast mode compatibility */ @media (prefers-contrast: high) { .${className} *:focus { outline-width: calc(${width} + 1px) !important; outline-color: ButtonText !important; } } /* Reduced motion compatibility */ @media (prefers-reduced-motion: reduce) { .${className} *:focus { transition: none !important; } } /* Dark mode compatibility */ @media (prefers-color-scheme: dark) { .${className} *:focus { outline-color: #66b3ff !important; } } /* Remove default focus for elements with our enhanced focus */ .${className} *:focus:not(:focus-visible) { outline: none !important; } /* Ensure focus-visible works properly */ .${className} *:focus-visible { outline: ${width} ${style} ${color} !important; outline-offset: ${offset} !important; } `; } /** * Create a focus ring with high contrast settings */ static createHighContrast(options = {}) { return new AccessibleFocusRing({ color: "#ffff00", width: "4px", offset: "3px", style: "solid", ...options }); } /** * Create a focus ring optimized for dark themes */ static createDarkTheme(options = {}) { return new AccessibleFocusRing({ color: "#66b3ff", width: "3px", offset: "2px", style: "solid", ...options }); } /** * Create a focus ring for users who prefer reduced motion */ static createReducedMotion(options = {}) { return new AccessibleFocusRing({ duration: "0s", ...options }); } } export { AccessibleFocusRing }; //# sourceMappingURL=focus-ring.js.map