@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/components/ui/accessibility-demo.esm.js +30 -24
  3. package/dist/components/ui/accessibility-demo.js +30 -24
  4. package/dist/components/ui/advanced-component-architecture-demo.esm.js +235 -179
  5. package/dist/components/ui/advanced-component-architecture-demo.js +235 -179
  6. package/dist/components/ui/advanced-transition-system-demo.esm.js +110 -64
  7. package/dist/components/ui/advanced-transition-system-demo.js +110 -64
  8. package/dist/components/ui/advanced-transition-system.esm.js +166 -122
  9. package/dist/components/ui/advanced-transition-system.js +166 -122
  10. package/dist/components/ui/animation/animated-container.esm.js +52 -29
  11. package/dist/components/ui/animation/animated-container.js +52 -29
  12. package/dist/components/ui/animation/staggered-container.esm.js +18 -9
  13. package/dist/components/ui/animation/staggered-container.js +18 -9
  14. package/dist/components/ui/animation-demo.esm.js +67 -35
  15. package/dist/components/ui/animation-demo.js +67 -35
  16. package/dist/components/ui/badge.esm.js +9 -6
  17. package/dist/components/ui/badge.js +9 -6
  18. package/dist/components/ui/battery-conscious-animation-demo.esm.js +122 -87
  19. package/dist/components/ui/battery-conscious-animation-demo.js +122 -87
  20. package/dist/components/ui/border-radius-shadow-demo.esm.js +23 -12
  21. package/dist/components/ui/border-radius-shadow-demo.js +23 -12
  22. package/dist/components/ui/button.esm.js +8 -2
  23. package/dist/components/ui/button.js +8 -2
  24. package/dist/components/ui/card.esm.js +33 -8
  25. package/dist/components/ui/card.js +33 -8
  26. package/dist/components/ui/checkbox.esm.js +3 -3
  27. package/dist/components/ui/checkbox.js +3 -3
  28. package/dist/components/ui/color-preview.esm.js +68 -45
  29. package/dist/components/ui/color-preview.js +68 -45
  30. package/dist/components/ui/data-display/chart.esm.js +112 -84
  31. package/dist/components/ui/data-display/chart.js +112 -84
  32. package/dist/components/ui/data-display/data-grid-simple.esm.js +1 -1
  33. package/dist/components/ui/data-display/data-grid-simple.js +1 -1
  34. package/dist/components/ui/data-display/data-grid.esm.js +80 -67
  35. package/dist/components/ui/data-display/data-grid.js +80 -67
  36. package/dist/components/ui/data-display/list.esm.js +53 -45
  37. package/dist/components/ui/data-display/list.js +53 -45
  38. package/dist/components/ui/data-display/table.esm.js +62 -54
  39. package/dist/components/ui/data-display/table.js +62 -54
  40. package/dist/components/ui/data-display/timeline.esm.js +39 -34
  41. package/dist/components/ui/data-display/timeline.js +39 -34
  42. package/dist/components/ui/data-display/tree.esm.js +116 -84
  43. package/dist/components/ui/data-display/tree.js +116 -84
  44. package/dist/components/ui/data-display/types.esm.js +389 -364
  45. package/dist/components/ui/data-display/types.js +389 -364
  46. package/dist/components/ui/enterprise-mobile-experience-demo.esm.js +120 -70
  47. package/dist/components/ui/enterprise-mobile-experience-demo.js +120 -70
  48. package/dist/components/ui/enterprise-mobile-experience.esm.js +124 -73
  49. package/dist/components/ui/enterprise-mobile-experience.js +124 -73
  50. package/dist/components/ui/feedback/alert.esm.js +22 -15
  51. package/dist/components/ui/feedback/alert.js +22 -15
  52. package/dist/components/ui/feedback/progress.esm.js +47 -24
  53. package/dist/components/ui/feedback/progress.js +47 -24
  54. package/dist/components/ui/feedback/skeleton.esm.js +39 -29
  55. package/dist/components/ui/feedback/skeleton.js +39 -29
  56. package/dist/components/ui/feedback/toast.esm.js +62 -38
  57. package/dist/components/ui/feedback/toast.js +62 -38
  58. package/dist/components/ui/feedback/types.esm.js +83 -83
  59. package/dist/components/ui/feedback/types.js +83 -83
  60. package/dist/components/ui/font-preview.esm.js +41 -39
  61. package/dist/components/ui/font-preview.js +41 -39
  62. package/dist/components/ui/form-demo.esm.js +150 -113
  63. package/dist/components/ui/form-demo.js +150 -113
  64. package/dist/components/ui/hardware-acceleration-demo.esm.js +137 -87
  65. package/dist/components/ui/hardware-acceleration-demo.js +137 -87
  66. package/dist/components/ui/input.esm.js +4 -1
  67. package/dist/components/ui/input.js +4 -1
  68. package/dist/components/ui/layout-demo.esm.js +81 -56
  69. package/dist/components/ui/layout-demo.js +81 -56
  70. package/dist/components/ui/layouts/adaptive-layout.esm.js +27 -8
  71. package/dist/components/ui/layouts/adaptive-layout.js +27 -8
  72. package/dist/components/ui/layouts/desktop-layout.esm.js +39 -19
  73. package/dist/components/ui/layouts/desktop-layout.js +39 -19
  74. package/dist/components/ui/layouts/mobile-layout.esm.js +19 -9
  75. package/dist/components/ui/layouts/mobile-layout.js +19 -9
  76. package/dist/components/ui/layouts/tablet-layout.esm.js +28 -14
  77. package/dist/components/ui/layouts/tablet-layout.js +28 -14
  78. package/dist/components/ui/mobile-form-validation.esm.js +120 -87
  79. package/dist/components/ui/mobile-form-validation.js +120 -87
  80. package/dist/components/ui/mobile-input-demo.esm.js +19 -13
  81. package/dist/components/ui/mobile-input-demo.js +19 -13
  82. package/dist/components/ui/mobile-input.esm.js +185 -120
  83. package/dist/components/ui/mobile-input.js +185 -120
  84. package/dist/components/ui/mobile-skeleton-loading-demo.esm.js +128 -111
  85. package/dist/components/ui/mobile-skeleton-loading-demo.js +128 -111
  86. package/dist/components/ui/navigation/breadcrumb.esm.js +17 -14
  87. package/dist/components/ui/navigation/breadcrumb.js +17 -14
  88. package/dist/components/ui/navigation/index.esm.js +23 -1
  89. package/dist/components/ui/navigation/index.js +23 -1
  90. package/dist/components/ui/navigation/menu.esm.js +49 -35
  91. package/dist/components/ui/navigation/menu.js +49 -35
  92. package/dist/components/ui/navigation/navigation-demo.esm.js +81 -74
  93. package/dist/components/ui/navigation/navigation-demo.js +81 -74
  94. package/dist/components/ui/navigation/pagination.esm.js +62 -50
  95. package/dist/components/ui/navigation/pagination.js +62 -50
  96. package/dist/components/ui/navigation/sidebar.esm.js +56 -42
  97. package/dist/components/ui/navigation/sidebar.js +56 -42
  98. package/dist/components/ui/navigation/stepper.esm.js +34 -23
  99. package/dist/components/ui/navigation/stepper.js +34 -23
  100. package/dist/components/ui/navigation/tabs.esm.js +32 -21
  101. package/dist/components/ui/navigation/tabs.js +32 -21
  102. package/dist/components/ui/navigation/types.esm.js +196 -195
  103. package/dist/components/ui/navigation/types.js +196 -195
  104. package/dist/components/ui/overlay/backdrop.esm.js +17 -16
  105. package/dist/components/ui/overlay/backdrop.js +17 -16
  106. package/dist/components/ui/overlay/focus-manager.esm.js +21 -19
  107. package/dist/components/ui/overlay/focus-manager.js +21 -19
  108. package/dist/components/ui/overlay/index.esm.js +22 -2
  109. package/dist/components/ui/overlay/index.js +22 -2
  110. package/dist/components/ui/overlay/modal.esm.js +38 -34
  111. package/dist/components/ui/overlay/modal.js +38 -34
  112. package/dist/components/ui/overlay/overlay-manager.esm.js +25 -20
  113. package/dist/components/ui/overlay/overlay-manager.js +25 -20
  114. package/dist/components/ui/overlay/popover.esm.js +74 -58
  115. package/dist/components/ui/overlay/popover.js +74 -58
  116. package/dist/components/ui/overlay/portal.esm.js +7 -7
  117. package/dist/components/ui/overlay/portal.js +7 -7
  118. package/dist/components/ui/overlay/tooltip.esm.js +54 -39
  119. package/dist/components/ui/overlay/tooltip.js +54 -39
  120. package/dist/components/ui/overlay/types.esm.js +132 -131
  121. package/dist/components/ui/overlay/types.js +132 -131
  122. package/dist/components/ui/performance-demo.esm.js +135 -88
  123. package/dist/components/ui/performance-demo.js +135 -88
  124. package/dist/components/ui/semantic-input-system-demo.esm.js +117 -80
  125. package/dist/components/ui/semantic-input-system-demo.js +117 -80
  126. package/dist/components/ui/theme-customizer.esm.js +84 -52
  127. package/dist/components/ui/theme-customizer.js +84 -52
  128. package/dist/components/ui/theme-preview.esm.js +95 -43
  129. package/dist/components/ui/theme-preview.js +95 -43
  130. package/dist/components/ui/theme-switcher.esm.js +70 -44
  131. package/dist/components/ui/theme-switcher.js +70 -44
  132. package/dist/components/ui/theme-toggle.esm.js +3 -3
  133. package/dist/components/ui/theme-toggle.js +3 -3
  134. package/dist/components/ui/token-demo.esm.js +33 -21
  135. package/dist/components/ui/token-demo.js +33 -21
  136. package/dist/components/ui/touch-demo.esm.js +102 -73
  137. package/dist/components/ui/touch-demo.js +102 -73
  138. package/dist/components/ui/touch-friendly-interface-demo.esm.js +102 -64
  139. package/dist/components/ui/touch-friendly-interface-demo.js +102 -64
  140. package/dist/components/ui/touch-friendly-interface.esm.js +85 -61
  141. package/dist/components/ui/touch-friendly-interface.js +85 -61
  142. package/dist/hooks/use-accessibility-support.esm.js +115 -85
  143. package/dist/hooks/use-accessibility-support.js +115 -85
  144. package/dist/hooks/use-adaptive-layout.esm.js +56 -33
  145. package/dist/hooks/use-adaptive-layout.js +56 -33
  146. package/dist/hooks/use-advanced-patterns.esm.js +57 -42
  147. package/dist/hooks/use-advanced-patterns.js +57 -42
  148. package/dist/hooks/use-advanced-transition-system.esm.js +112 -71
  149. package/dist/hooks/use-advanced-transition-system.js +112 -71
  150. package/dist/hooks/use-animation-profile.esm.js +63 -34
  151. package/dist/hooks/use-animation-profile.js +63 -34
  152. package/dist/hooks/use-battery-animations.esm.js +80 -55
  153. package/dist/hooks/use-battery-animations.js +80 -55
  154. package/dist/hooks/use-battery-conscious-loading.esm.js +166 -123
  155. package/dist/hooks/use-battery-conscious-loading.js +166 -123
  156. package/dist/hooks/use-battery-optimization.esm.js +78 -55
  157. package/dist/hooks/use-battery-optimization.js +78 -55
  158. package/dist/hooks/use-battery-status.esm.js +73 -51
  159. package/dist/hooks/use-battery-status.js +73 -51
  160. package/dist/hooks/use-component-performance.esm.js +62 -47
  161. package/dist/hooks/use-component-performance.js +62 -47
  162. package/dist/hooks/use-device-loading-states.esm.js +152 -109
  163. package/dist/hooks/use-device-loading-states.js +152 -109
  164. package/dist/hooks/use-device.esm.js +25 -14
  165. package/dist/hooks/use-device.js +25 -14
  166. package/dist/hooks/use-enterprise-mobile-experience.esm.js +137 -88
  167. package/dist/hooks/use-enterprise-mobile-experience.js +137 -88
  168. package/dist/hooks/use-form-feedback.esm.js +124 -81
  169. package/dist/hooks/use-form-feedback.js +124 -81
  170. package/dist/hooks/use-form-performance.esm.js +127 -92
  171. package/dist/hooks/use-form-performance.js +127 -92
  172. package/dist/hooks/use-frame-rate.esm.js +56 -37
  173. package/dist/hooks/use-frame-rate.js +56 -37
  174. package/dist/hooks/use-gestures.esm.js +96 -72
  175. package/dist/hooks/use-gestures.js +96 -72
  176. package/dist/hooks/use-hardware-acceleration.esm.js +65 -37
  177. package/dist/hooks/use-hardware-acceleration.js +65 -37
  178. package/dist/hooks/use-input-accessibility.esm.js +157 -119
  179. package/dist/hooks/use-input-accessibility.js +157 -119
  180. package/dist/hooks/use-input-performance.esm.js +139 -104
  181. package/dist/hooks/use-input-performance.js +139 -104
  182. package/dist/hooks/use-layout-performance.esm.js +50 -29
  183. package/dist/hooks/use-layout-performance.js +50 -29
  184. package/dist/hooks/use-loading-accessibility.esm.js +209 -169
  185. package/dist/hooks/use-loading-accessibility.js +209 -169
  186. package/dist/hooks/use-loading-performance.esm.js +117 -93
  187. package/dist/hooks/use-loading-performance.js +117 -93
  188. package/dist/hooks/use-memory-usage.esm.js +57 -38
  189. package/dist/hooks/use-memory-usage.js +57 -38
  190. package/dist/hooks/use-mobile-form-layout.esm.js +111 -74
  191. package/dist/hooks/use-mobile-form-layout.js +111 -74
  192. package/dist/hooks/use-mobile-form-validation.esm.js +211 -144
  193. package/dist/hooks/use-mobile-form-validation.js +211 -144
  194. package/dist/hooks/use-mobile-keyboard-optimization.esm.js +154 -113
  195. package/dist/hooks/use-mobile-keyboard-optimization.js +154 -113
  196. package/dist/hooks/use-mobile-layout.esm.js +73 -51
  197. package/dist/hooks/use-mobile-layout.js +73 -51
  198. package/dist/hooks/use-mobile-optimization.esm.js +72 -44
  199. package/dist/hooks/use-mobile-optimization.js +72 -44
  200. package/dist/hooks/use-mobile-skeleton.esm.js +97 -64
  201. package/dist/hooks/use-mobile-skeleton.js +97 -64
  202. package/dist/hooks/use-mobile-touch.esm.js +128 -93
  203. package/dist/hooks/use-mobile-touch.js +128 -93
  204. package/dist/hooks/use-performance-throttling.esm.js +72 -48
  205. package/dist/hooks/use-performance-throttling.js +72 -48
  206. package/dist/hooks/use-performance.esm.js +90 -52
  207. package/dist/hooks/use-performance.js +90 -52
  208. package/dist/hooks/use-reusable-architecture.esm.js +94 -65
  209. package/dist/hooks/use-reusable-architecture.js +94 -65
  210. package/dist/hooks/use-semantic-input-types.esm.js +166 -124
  211. package/dist/hooks/use-semantic-input-types.js +166 -124
  212. package/dist/hooks/use-semantic-input.esm.js +178 -126
  213. package/dist/hooks/use-semantic-input.js +178 -126
  214. package/dist/hooks/use-tablet-layout.esm.js +67 -38
  215. package/dist/hooks/use-tablet-layout.js +67 -38
  216. package/dist/hooks/use-touch-friendly-input.esm.js +193 -149
  217. package/dist/hooks/use-touch-friendly-input.js +193 -149
  218. package/dist/hooks/use-touch-friendly-interface.esm.js +99 -67
  219. package/dist/hooks/use-touch-friendly-interface.js +99 -67
  220. package/dist/hooks/use-touch-optimization.esm.js +99 -72
  221. package/dist/hooks/use-touch-optimization.js +99 -72
  222. package/dist/index.esm.js +289 -280
  223. package/dist/index.js +289 -280
  224. package/dist/lib/utils.esm.js +1 -1
  225. package/dist/lib/utils.js +1 -1
  226. package/dist/plugins/theme-css-generator.esm.js +104 -55
  227. package/dist/plugins/theme-css-generator.js +104 -55
  228. package/dist/provider.esm.js +4 -4
  229. package/dist/provider.js +4 -4
  230. package/dist/styles.css +1 -1
  231. package/dist/theme.esm.js +633 -468
  232. package/dist/theme.js +633 -468
  233. package/dist/themes/ThemeContext.esm.js +15 -15
  234. package/dist/themes/ThemeContext.js +15 -15
  235. package/dist/themes/ThemeProvider.esm.js +25 -22
  236. package/dist/themes/ThemeProvider.js +25 -22
  237. package/dist/themes/accessibility.esm.js +147 -108
  238. package/dist/themes/accessibility.js +147 -108
  239. package/dist/themes/aria-patterns.esm.js +198 -162
  240. package/dist/themes/aria-patterns.js +198 -162
  241. package/dist/themes/base-themes.esm.js +14 -11
  242. package/dist/themes/base-themes.js +14 -11
  243. package/dist/themes/colorManager.esm.js +101 -83
  244. package/dist/themes/colorManager.js +101 -83
  245. package/dist/themes/examples/dark-theme.esm.js +133 -103
  246. package/dist/themes/examples/dark-theme.js +133 -103
  247. package/dist/themes/examples/minimal-theme.esm.js +83 -61
  248. package/dist/themes/examples/minimal-theme.js +83 -61
  249. package/dist/themes/focus-management.esm.js +202 -143
  250. package/dist/themes/focus-management.js +202 -143
  251. package/dist/themes/fontLoader.esm.js +28 -19
  252. package/dist/themes/fontLoader.js +28 -19
  253. package/dist/themes/high-contrast.esm.js +152 -104
  254. package/dist/themes/high-contrast.js +152 -104
  255. package/dist/themes/inheritance.esm.js +35 -27
  256. package/dist/themes/inheritance.js +35 -27
  257. package/dist/themes/keyboard-navigation.esm.js +152 -123
  258. package/dist/themes/keyboard-navigation.js +152 -123
  259. package/dist/themes/motion-reduction.esm.js +193 -133
  260. package/dist/themes/motion-reduction.js +193 -133
  261. package/dist/themes/navigation.esm.js +146 -146
  262. package/dist/themes/navigation.js +146 -146
  263. package/dist/themes/screen-reader.esm.js +159 -94
  264. package/dist/themes/screen-reader.js +159 -94
  265. package/dist/themes/systemThemeDetector.esm.js +42 -34
  266. package/dist/themes/systemThemeDetector.js +42 -34
  267. package/dist/themes/themeCSSUpdater.esm.js +21 -9
  268. package/dist/themes/themeCSSUpdater.js +21 -9
  269. package/dist/themes/themePersistence.esm.js +68 -47
  270. package/dist/themes/themePersistence.js +68 -47
  271. package/dist/themes/themes/stan-design.esm.js +633 -468
  272. package/dist/themes/themes/stan-design.js +633 -468
  273. package/dist/themes/types.esm.js +301 -287
  274. package/dist/themes/types.js +301 -287
  275. package/dist/themes/useSystemTheme.esm.js +4 -4
  276. package/dist/themes/useSystemTheme.js +4 -4
  277. package/dist/themes/useTheme.esm.js +4 -4
  278. package/dist/themes/useTheme.js +4 -4
  279. package/dist/themes/validation.esm.js +128 -77
  280. package/dist/themes/validation.js +128 -77
  281. package/dist/tokens/index.esm.js +15 -4
  282. package/dist/tokens/index.js +15 -4
  283. package/dist/tokens/tokenExporter.esm.js +87 -61
  284. package/dist/tokens/tokenExporter.js +87 -61
  285. package/dist/tokens/tokenGenerator.esm.js +86 -77
  286. package/dist/tokens/tokenGenerator.js +86 -77
  287. package/dist/tokens/tokenManager.esm.js +64 -51
  288. package/dist/tokens/tokenManager.js +64 -51
  289. package/dist/tokens/tokenValidator.esm.js +193 -147
  290. package/dist/tokens/tokenValidator.js +193 -147
  291. package/dist/tokens/types.esm.js +49 -35
  292. package/dist/tokens/types.js +49 -35
  293. package/dist/utils/bundle-analyzer.esm.js +83 -65
  294. package/dist/utils/bundle-analyzer.js +83 -65
  295. package/dist/utils/bundle-splitting.esm.js +142 -117
  296. package/dist/utils/bundle-splitting.js +142 -117
  297. package/dist/utils/lazy-loading.esm.js +132 -106
  298. package/dist/utils/lazy-loading.js +132 -106
  299. package/dist/utils/performance-monitor.esm.js +170 -129
  300. package/dist/utils/performance-monitor.js +170 -129
  301. package/dist/utils/tree-shaking.esm.js +69 -61
  302. package/dist/utils/tree-shaking.js +69 -61
  303. package/package.json +1 -1
  304. package/src/index.ts +146 -146
@@ -2,21 +2,21 @@ import { screenReaderOptimizer } from './screen-reader';
2
2
 
3
3
  // Focus management utilities
4
4
  export class AccessibilityFocusManager {
5
- private focusableSelectors];
6
- private focusableElements];
7
- private lastFocusedElement;
8
- private focusTraps, FocusTrap>;
9
- private focusHistory];
10
- private maxHistorySize;
5
+ private focusableSelectors: string[];
6
+ private focusableElements: HTMLElement[];
7
+ private lastFocusedElement: HTMLElement | null;
8
+ private focusTraps: Map<string, FocusTrap>;
9
+ private focusHistory: HTMLElement[];
10
+ private maxHistorySize: number;
11
11
 
12
12
  constructor() {
13
13
  this.focusableSelectors = [
14
14
  'a[href]',
15
- 'button])',
16
- 'input])',
17
- 'select])',
18
- 'textarea])',
19
- '[tabindex]="-1"])',
15
+ 'button:not([disabled])',
16
+ 'input:not([disabled])',
17
+ 'select:not([disabled])',
18
+ 'textarea:not([disabled])',
19
+ '[tabindex]:not([tabindex="-1"])',
20
20
  '[contenteditable="true"]',
21
21
  'audio[controls]',
22
22
  'video[controls]',
@@ -33,18 +33,22 @@ export class AccessibilityFocusManager {
33
33
  }
34
34
 
35
35
  // Initialize focus management
36
- private initialize());
36
+ private initialize(): void {
37
+ this.updateFocusableElements();
37
38
  this.setupEventListeners();
38
39
  }
39
40
 
40
41
  // Update list of focusable elements
41
- private updateFocusableElements()= Array.from(
42
+ private updateFocusableElements(): void {
43
+ this.focusableElements = Array.from(
42
44
  document.querySelectorAll(this.focusableSelectors.join(','))
43
45
  ) as HTMLElement[];
44
46
  }
45
47
 
46
48
  // Setup event listeners
47
- private setupEventListeners(), this.handleFocusIn.bind(this));
49
+ private setupEventListeners(): void {
50
+ // Track focus changes
51
+ document.addEventListener('focusin', this.handleFocusIn.bind(this));
48
52
  document.addEventListener('focusout', this.handleFocusOut.bind(this));
49
53
 
50
54
  // Handle tab key navigation
@@ -56,12 +60,14 @@ export class AccessibilityFocusManager {
56
60
  });
57
61
 
58
62
  observer.observe(document.body, {
59
- childList,
60
- subtree});
63
+ childList: true,
64
+ subtree: true
65
+ });
61
66
  }
62
67
 
63
68
  // Handle focus in events
64
- private handleFocusIn(event)= event.target as HTMLElement;
69
+ private handleFocusIn(event: FocusEvent): void {
70
+ const target = event.target as HTMLElement;
65
71
 
66
72
  if (target && target !== this.lastFocusedElement) {
67
73
  // Add to focus history
@@ -81,16 +87,20 @@ export class AccessibilityFocusManager {
81
87
  }
82
88
 
83
89
  // Handle focus out events
84
- private handleFocusOut(_event)}
90
+ private handleFocusOut(_event: FocusEvent): void {
91
+ // Focus out handling if needed
92
+ }
85
93
 
86
94
  // Handle key down events
87
- private handleKeyDown(event)=== 'Tab') {
95
+ private handleKeyDown(event: KeyboardEvent): void {
96
+ if (event.key === 'Tab') {
88
97
  this.handleTabNavigation(event);
89
98
  }
90
99
  }
91
100
 
92
101
  // Handle tab navigation
93
- private handleTabNavigation(event)= event.shiftKey;
102
+ private handleTabNavigation(event: KeyboardEvent): void {
103
+ const isShiftTab = event.shiftKey;
94
104
  const currentElement = event.target as HTMLElement;
95
105
 
96
106
  // Check if we're in a focus trap
@@ -106,7 +116,8 @@ export class AccessibilityFocusManager {
106
116
  }
107
117
 
108
118
  // Get active focus trap for element
109
- private getActiveFocusTrap(element))) {
119
+ private getActiveFocusTrap(element: HTMLElement): FocusTrap | null {
120
+ for (const trap of this.focusTraps.values()) {
110
121
  if (trap.isActive && trap.container.contains(element)) {
111
122
  return trap;
112
123
  }
@@ -115,36 +126,40 @@ export class AccessibilityFocusManager {
115
126
  }
116
127
 
117
128
  // Navigate within a focus trap
118
- private navigateInFocusTrap(trap, isShiftTab)= trap.getFocusableElements();
129
+ private navigateInFocusTrap(trap: FocusTrap, isShiftTab: boolean): void {
130
+ const focusableElements = trap.getFocusableElements();
119
131
  if (focusableElements.length === 0) return;
120
132
 
121
133
  const currentIndex = focusableElements.indexOf(document.activeElement as HTMLElement);
122
- let nextIndex;
134
+ let nextIndex: number;
123
135
 
124
136
  if (isShiftTab) {
125
- nextIndex = currentIndex > 0 ? currentIndex - 1 ;
137
+ nextIndex = currentIndex > 0 ? currentIndex - 1 : focusableElements.length - 1;
126
138
  } else {
127
- nextIndex = currentIndex < focusableElements.length - 1 ? currentIndex + 1 ;
139
+ nextIndex = currentIndex < focusableElements.length - 1 ? currentIndex + 1 : 0;
128
140
  }
129
141
 
130
142
  focusableElements[nextIndex]?.focus();
131
143
  }
132
144
 
133
145
  // Navigate focusable elements
134
- private navigateFocusableElements(isShiftTab)= this.focusableElements.indexOf(document.activeElement as HTMLElement);
135
- let nextIndex;
146
+ private navigateFocusableElements(isShiftTab: boolean): void {
147
+ const currentIndex = this.focusableElements.indexOf(document.activeElement as HTMLElement);
148
+ let nextIndex: number;
136
149
 
137
150
  if (isShiftTab) {
138
- nextIndex = currentIndex > 0 ? currentIndex - 1 ;
151
+ nextIndex = currentIndex > 0 ? currentIndex - 1 : this.focusableElements.length - 1;
139
152
  } else {
140
- nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 ;
153
+ nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 : 0;
141
154
  }
142
155
 
143
156
  this.focusableElements[nextIndex]?.focus();
144
157
  }
145
158
 
146
159
  // Add element to focus history
147
- private addToFocusHistory(element)= this.focusHistory.filter(el => el !== element);
160
+ private addToFocusHistory(element: HTMLElement): void {
161
+ // Remove if already exists
162
+ this.focusHistory = this.focusHistory.filter(el => el !== element);
148
163
 
149
164
  // Add to beginning
150
165
  this.focusHistory.unshift(element);
@@ -156,7 +171,8 @@ export class AccessibilityFocusManager {
156
171
  }
157
172
 
158
173
  // Get element description for screen readers
159
- private getElementDescription(element)= element.getAttribute('aria-label');
174
+ private getElementDescription(element: HTMLElement): string {
175
+ const ariaLabel = element.getAttribute('aria-label');
160
176
  if (ariaLabel) return ariaLabel;
161
177
 
162
178
  const ariaLabelledBy = element.getAttribute('aria-labelledby');
@@ -175,7 +191,9 @@ export class AccessibilityFocusManager {
175
191
  }
176
192
 
177
193
  // Get element context for screen readers
178
- private getElementContext(element)= element.closest('[role], section, article, aside, nav, header, footer, main');
194
+ private getElementContext(element: HTMLElement): string | undefined {
195
+ // Find nearest landmark or section
196
+ const landmark = element.closest('[role], section, article, aside, nav, header, footer, main');
179
197
  if (landmark) {
180
198
  const role = landmark.getAttribute('role');
181
199
  const ariaLabel = landmark.getAttribute('aria-label');
@@ -185,13 +203,15 @@ export class AccessibilityFocusManager {
185
203
  }
186
204
 
187
205
  // Create focus trap
188
- createFocusTrap(container, options= {})= new FocusTrap(container, options);
206
+ createFocusTrap(container: HTMLElement, options: FocusTrapOptions = {}): FocusTrap {
207
+ const trap = new FocusTrap(container, options);
189
208
  this.focusTraps.set(trap.id, trap);
190
209
  return trap;
191
210
  }
192
211
 
193
212
  // Remove focus trap
194
- removeFocusTrap(trapId)= this.focusTraps.get(trapId);
213
+ removeFocusTrap(trapId: string): void {
214
+ const trap = this.focusTraps.get(trapId);
195
215
  if (trap) {
196
216
  trap.deactivate();
197
217
  this.focusTraps.delete(trapId);
@@ -199,104 +219,119 @@ export class AccessibilityFocusManager {
199
219
  }
200
220
 
201
221
  // Focus first focusable element
202
- focusFirst()= this.focusableElements[0];
222
+ focusFirst(): void {
223
+ const firstElement = this.focusableElements[0];
203
224
  if (firstElement) {
204
225
  firstElement.focus();
205
226
  }
206
227
  }
207
228
 
208
229
  // Focus last focusable element
209
- focusLast()= this.focusableElements[this.focusableElements.length - 1];
230
+ focusLast(): void {
231
+ const lastElement = this.focusableElements[this.focusableElements.length - 1];
210
232
  if (lastElement) {
211
233
  lastElement.focus();
212
234
  }
213
235
  }
214
236
 
215
237
  // Focus next element
216
- focusNext()= this.focusableElements.indexOf(document.activeElement as HTMLElement);
217
- const nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 ;
238
+ focusNext(): void {
239
+ const currentIndex = this.focusableElements.indexOf(document.activeElement as HTMLElement);
240
+ const nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 : 0;
218
241
  this.focusableElements[nextIndex]?.focus();
219
242
  }
220
243
 
221
244
  // Focus previous element
222
- focusPrevious()= this.focusableElements.indexOf(document.activeElement as HTMLElement);
223
- const prevIndex = currentIndex > 0 ? currentIndex - 1 ;
245
+ focusPrevious(): void {
246
+ const currentIndex = this.focusableElements.indexOf(document.activeElement as HTMLElement);
247
+ const prevIndex = currentIndex > 0 ? currentIndex - 1 : this.focusableElements.length - 1;
224
248
  this.focusableElements[prevIndex]?.focus();
225
249
  }
226
250
 
227
251
  // Focus element by index
228
- focusByIndex(index)= 0 && index < this.focusableElements.length) {
252
+ focusByIndex(index: number): void {
253
+ if (index >= 0 && index < this.focusableElements.length) {
229
254
  this.focusableElements[index].focus();
230
255
  }
231
256
  }
232
257
 
233
258
  // Focus element by ID
234
- focusById(id)= document.getElementById(id);
259
+ focusById(id: string): void {
260
+ const element = document.getElementById(id);
235
261
  if (element && this.focusableElements.includes(element)) {
236
262
  element.focus();
237
263
  }
238
264
  }
239
265
 
240
266
  // Focus element by data attribute
241
- focusByDataAttribute(attribute, value)= document.querySelector(`[data-${attribute}="${value}"]`) as HTMLElement;
267
+ focusByDataAttribute(attribute: string, value: string): void {
268
+ const element = document.querySelector(`[data-${attribute}="${value}"]`) as HTMLElement;
242
269
  if (element && this.focusableElements.includes(element)) {
243
270
  element.focus();
244
271
  }
245
272
  }
246
273
 
247
274
  // Restore previous focus
248
- restoreFocus()== null) {
275
+ restoreFocus(): void {
276
+ if (this.lastFocusedElement && this.lastFocusedElement.offsetParent !== null) {
249
277
  this.lastFocusedElement.focus();
250
278
  }
251
279
  }
252
280
 
253
281
  // Get focus history
254
- getFocusHistory()] {
282
+ getFocusHistory(): HTMLElement[] {
255
283
  return [...this.focusHistory];
256
284
  }
257
285
 
258
286
  // Clear focus history
259
- clearFocusHistory()= [];
287
+ clearFocusHistory(): void {
288
+ this.focusHistory = [];
260
289
  }
261
290
 
262
291
  // Get current focus information
263
- getCurrentFocusInfo();
264
- index;
265
- total;
266
- context;
292
+ getCurrentFocusInfo(): {
293
+ element: HTMLElement | null;
294
+ index: number;
295
+ total: number;
296
+ context: string | undefined;
267
297
  } {
268
298
  const currentElement = document.activeElement as HTMLElement;
269
299
  const index = this.focusableElements.indexOf(currentElement);
270
300
 
271
301
  return {
272
- element,
273
- index= 0 ? index ,
274
- total,
275
- context) };
302
+ element: currentElement,
303
+ index: index >= 0 ? index : -1,
304
+ total: this.focusableElements.length,
305
+ context: currentElement ? this.getElementContext(currentElement) : undefined
306
+ };
276
307
  }
277
308
 
278
309
  // Check if element is focusable
279
- isFocusable(element));
310
+ isFocusable(element: HTMLElement): boolean {
311
+ return this.focusableElements.includes(element);
280
312
  }
281
313
 
282
314
  // Get all focusable elements
283
- getAllFocusableElements()] {
315
+ getAllFocusableElements(): HTMLElement[] {
284
316
  return [...this.focusableElements];
285
317
  }
286
318
 
287
319
  // Get focusable elements within container
288
- getFocusableElementsInContainer(container)] {
320
+ getFocusableElementsInContainer(container: HTMLElement): HTMLElement[] {
289
321
  return this.focusableElements.filter(element =>
290
322
  container.contains(element)
291
323
  );
292
324
  }
293
325
 
294
326
  // Update focusable elements manually
295
- refreshFocusableElements());
327
+ refreshFocusableElements(): void {
328
+ this.updateFocusableElements();
296
329
  }
297
330
 
298
331
  // Destroy focus manager
299
- destroy()=> trap.deactivate());
332
+ destroy(): void {
333
+ // Remove all focus traps
334
+ this.focusTraps.forEach(trap => trap.deactivate());
300
335
  this.focusTraps.clear();
301
336
 
302
337
  // Clear focus history
@@ -311,41 +346,42 @@ export class AccessibilityFocusManager {
311
346
 
312
347
  // Focus trap options
313
348
  export interface FocusTrapOptions {
314
- autoFocus?;
315
- returnFocus?;
316
- escapeDeactivates?;
317
- clickOutsideDeactivates?;
318
- allowOutsideClick?;
319
- fallbackFocus?;
349
+ autoFocus?: boolean;
350
+ returnFocus?: boolean;
351
+ escapeDeactivates?: boolean;
352
+ clickOutsideDeactivates?: boolean;
353
+ allowOutsideClick?: boolean;
354
+ fallbackFocus?: HTMLElement;
320
355
  }
321
356
 
322
357
  // Focus trap class
323
358
  export class FocusTrap {
324
- public readonly id;
325
- public readonly container;
326
- public readonly options;
327
- public isActive= false;
359
+ public readonly id: string;
360
+ public readonly container: HTMLElement;
361
+ public readonly options: FocusTrapOptions;
362
+ public isActive: boolean = false;
328
363
 
329
- private returnFocusElement= null;
330
- private focusableElements] = [];
331
- private eventListeners; handler) => void }> = [];
364
+ private returnFocusElement: HTMLElement | null = null;
365
+ private focusableElements: HTMLElement[] = [];
366
+ private eventListeners: Array<{ event: string; handler: (event: any) => void }> = [];
332
367
 
333
- constructor(container, options= {}) {
368
+ constructor(container: HTMLElement, options: FocusTrapOptions = {}) {
334
369
  this.id = `focus-trap-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
335
370
  this.container = container;
336
371
  this.options = {
337
- autoFocus,
338
- returnFocus,
339
- escapeDeactivates,
340
- clickOutsideDeactivates,
341
- allowOutsideClick,
342
- fallbackFocus,
372
+ autoFocus: true,
373
+ returnFocus: true,
374
+ escapeDeactivates: true,
375
+ clickOutsideDeactivates: false,
376
+ allowOutsideClick: false,
377
+ fallbackFocus: container,
343
378
  ...options
344
379
  };
345
380
  }
346
381
 
347
382
  // Activate focus trap
348
- activate()) return;
383
+ activate(): void {
384
+ if (this.isActive) return;
349
385
 
350
386
  // Store current focus for return
351
387
  if (this.options.returnFocus) {
@@ -369,7 +405,8 @@ export class FocusTrap {
369
405
  }
370
406
 
371
407
  // Deactivate focus trap
372
- deactivate()) return;
408
+ deactivate(): void {
409
+ if (!this.isActive) return;
373
410
 
374
411
  // Remove event listeners
375
412
  this.removeEventListeners();
@@ -383,14 +420,14 @@ export class FocusTrap {
383
420
  }
384
421
 
385
422
  // Get focusable elements within container
386
- getFocusableElements()] {
423
+ getFocusableElements(): HTMLElement[] {
387
424
  const focusableSelectors = [
388
425
  'a[href]',
389
- 'button])',
390
- 'input])',
391
- 'select])',
392
- 'textarea])',
393
- '[tabindex]="-1"])',
426
+ 'button:not([disabled])',
427
+ 'input:not([disabled])',
428
+ 'select:not([disabled])',
429
+ 'textarea:not([disabled])',
430
+ '[tabindex]:not([tabindex="-1"])',
394
431
  '[contenteditable="true"]'
395
432
  ];
396
433
 
@@ -400,31 +437,33 @@ export class FocusTrap {
400
437
  }
401
438
 
402
439
  // Setup event listeners
403
- private setupEventListeners()) {
404
- const escapeHandler = (event) => {
440
+ private setupEventListeners(): void {
441
+ // Handle escape key
442
+ if (this.options.escapeDeactivates) {
443
+ const escapeHandler = (event: KeyboardEvent) => {
405
444
  if (event.key === 'Escape') {
406
445
  this.deactivate();
407
446
  }
408
447
  };
409
448
 
410
449
  document.addEventListener('keydown', escapeHandler);
411
- this.eventListeners.push({ event, handler});
450
+ this.eventListeners.push({ event: 'keydown', handler: escapeHandler });
412
451
  }
413
452
 
414
453
  // Handle click outside
415
454
  if (this.options.clickOutsideDeactivates) {
416
- const clickHandler = (event) => {
455
+ const clickHandler = (event: MouseEvent) => {
417
456
  if (!this.container.contains(event.target as Node)) {
418
457
  this.deactivate();
419
458
  }
420
459
  };
421
460
 
422
461
  document.addEventListener('click', clickHandler);
423
- this.eventListeners.push({ event, handler});
462
+ this.eventListeners.push({ event: 'click', handler: clickHandler });
424
463
  }
425
464
 
426
465
  // Handle tab key within trap
427
- const tabHandler = (event) => {
466
+ const tabHandler = (event: KeyboardEvent) => {
428
467
  if (event.key === 'Tab') {
429
468
  event.preventDefault();
430
469
  this.handleTabNavigation(event.shiftKey);
@@ -432,11 +471,12 @@ export class FocusTrap {
432
471
  };
433
472
 
434
473
  this.container.addEventListener('keydown', tabHandler);
435
- this.eventListeners.push({ event, handler});
474
+ this.eventListeners.push({ event: 'keydown', handler: tabHandler });
436
475
  }
437
476
 
438
477
  // Remove event listeners
439
- private removeEventListeners(), handler }) => {
478
+ private removeEventListeners(): void {
479
+ this.eventListeners.forEach(({ event, handler }) => {
440
480
  if (event === 'keydown' && handler.toString().includes('tabHandler')) {
441
481
  this.container.removeEventListener(event, handler);
442
482
  } else {
@@ -448,73 +488,81 @@ export class FocusTrap {
448
488
  }
449
489
 
450
490
  // Handle tab navigation within trap
451
- private handleTabNavigation(isShiftTab)=== 0) return;
491
+ private handleTabNavigation(isShiftTab: boolean): void {
492
+ if (this.focusableElements.length === 0) return;
452
493
 
453
494
  const currentIndex = this.focusableElements.indexOf(document.activeElement as HTMLElement);
454
- let nextIndex;
495
+ let nextIndex: number;
455
496
 
456
497
  if (isShiftTab) {
457
- nextIndex = currentIndex > 0 ? currentIndex - 1 ;
498
+ nextIndex = currentIndex > 0 ? currentIndex - 1 : this.focusableElements.length - 1;
458
499
  } else {
459
- nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 ;
500
+ nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 : 0;
460
501
  }
461
502
 
462
503
  this.focusableElements[nextIndex]?.focus();
463
504
  }
464
505
 
465
506
  // Focus first element in trap
466
- focusFirst()) {
507
+ focusFirst(): void {
508
+ if (this.focusableElements.length > 0) {
467
509
  this.focusableElements[0].focus();
468
510
  }
469
511
  }
470
512
 
471
513
  // Focus last element in trap
472
- focusLast()) {
514
+ focusLast(): void {
515
+ if (this.focusableElements.length > 0) {
473
516
  this.focusableElements[this.focusableElements.length - 1].focus();
474
517
  }
475
518
  }
476
519
 
477
520
  // Focus next element in trap
478
- focusNext()=== 0) return;
521
+ focusNext(): void {
522
+ if (this.focusableElements.length === 0) return;
479
523
 
480
524
  const currentIndex = this.focusableElements.indexOf(document.activeElement as HTMLElement);
481
- const nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 ;
525
+ const nextIndex = currentIndex < this.focusableElements.length - 1 ? currentIndex + 1 : 0;
482
526
  this.focusableElements[nextIndex]?.focus();
483
527
  }
484
528
 
485
529
  // Focus previous element in trap
486
- focusPrevious()=== 0) return;
530
+ focusPrevious(): void {
531
+ if (this.focusableElements.length === 0) return;
487
532
 
488
533
  const currentIndex = this.focusableElements.indexOf(document.activeElement as HTMLElement);
489
- const prevIndex = currentIndex > 0 ? currentIndex - 1 ;
534
+ const prevIndex = currentIndex > 0 ? currentIndex - 1 : this.focusableElements.length - 1;
490
535
  this.focusableElements[prevIndex]?.focus();
491
536
  }
492
537
 
493
538
  // Get trap information
494
- getInfo();
495
- isActive;
496
- focusableElementsCount;
497
- currentFocusIndex;
498
- container;
539
+ getInfo(): {
540
+ id: string;
541
+ isActive: boolean;
542
+ focusableElementsCount: number;
543
+ currentFocusIndex: number;
544
+ container: HTMLElement;
499
545
  } {
500
546
  const currentIndex = this.focusableElements.indexOf(document.activeElement as HTMLElement);
501
547
 
502
548
  return {
503
- id,
504
- isActive,
505
- focusableElementsCount,
506
- currentFocusIndex= 0 ? currentIndex ,
507
- container};
549
+ id: this.id,
550
+ isActive: this.isActive,
551
+ focusableElementsCount: this.focusableElements.length,
552
+ currentFocusIndex: currentIndex >= 0 ? currentIndex : -1,
553
+ container: this.container
554
+ };
508
555
  }
509
556
  }
510
557
 
511
558
  // Focus restoration utilities
512
559
  export class FocusRestoration {
513
- private focusStack] = [];
514
- private maxStackSize= 20;
560
+ private focusStack: HTMLElement[] = [];
561
+ private maxStackSize: number = 20;
515
562
 
516
563
  // Push current focus to stack
517
- pushFocus()= document.activeElement as HTMLElement;
564
+ pushFocus(): void {
565
+ const currentElement = document.activeElement as HTMLElement;
518
566
  if (currentElement && currentElement !== document.body) {
519
567
  this.focusStack.push(currentElement);
520
568
 
@@ -526,7 +574,8 @@ export class FocusRestoration {
526
574
  }
527
575
 
528
576
  // Pop and restore focus from stack
529
- popFocus()= this.focusStack.pop();
577
+ popFocus(): boolean {
578
+ const element = this.focusStack.pop();
530
579
  if (element && element.offsetParent !== null) {
531
580
  element.focus();
532
581
  return true;
@@ -535,28 +584,33 @@ export class FocusRestoration {
535
584
  }
536
585
 
537
586
  // Peek at top of focus stack
538
- peekFocus()];
587
+ peekFocus(): HTMLElement | undefined {
588
+ return this.focusStack[this.focusStack.length - 1];
539
589
  }
540
590
 
541
591
  // Clear focus stack
542
- clear()= [];
592
+ clear(): void {
593
+ this.focusStack = [];
543
594
  }
544
595
 
545
596
  // Get stack size
546
- getSize();
597
+ getSize(): number {
598
+ return this.focusStack.length;
547
599
  }
548
600
 
549
601
  // Check if stack is empty
550
- isEmpty()=== 0;
602
+ isEmpty(): boolean {
603
+ return this.focusStack.length === 0;
551
604
  }
552
605
  }
553
606
 
554
607
  // Focus navigation utilities
555
608
  export class FocusNavigation {
556
609
  // Navigate to next heading
557
- static focusNextHeading()= Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6'));
610
+ static focusNextHeading(): void {
611
+ const headings = Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6'));
558
612
  const currentIndex = headings.indexOf(document.activeElement as HTMLElement);
559
- const nextIndex = currentIndex < headings.length - 1 ? currentIndex + 1 ;
613
+ const nextIndex = currentIndex < headings.length - 1 ? currentIndex + 1 : 0;
560
614
 
561
615
  if (headings[nextIndex]) {
562
616
  (headings[nextIndex] as HTMLElement).focus();
@@ -564,9 +618,10 @@ export class FocusNavigation {
564
618
  }
565
619
 
566
620
  // Navigate to previous heading
567
- static focusPreviousHeading()= Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6'));
621
+ static focusPreviousHeading(): void {
622
+ const headings = Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6'));
568
623
  const currentIndex = headings.indexOf(document.activeElement as HTMLElement);
569
- const prevIndex = currentIndex > 0 ? currentIndex - 1 ;
624
+ const prevIndex = currentIndex > 0 ? currentIndex - 1 : headings.length - 1;
570
625
 
571
626
  if (headings[prevIndex]) {
572
627
  (headings[prevIndex] as HTMLElement).focus();
@@ -574,9 +629,10 @@ export class FocusNavigation {
574
629
  }
575
630
 
576
631
  // Navigate to next landmark
577
- static focusNextLandmark()= Array.from(document.querySelectorAll('[role="banner"], [role="main"], [role="navigation"], [role="complementary"], [role="contentinfo"]'));
632
+ static focusNextLandmark(): void {
633
+ const landmarks = Array.from(document.querySelectorAll('[role="banner"], [role="main"], [role="navigation"], [role="complementary"], [role="contentinfo"]'));
578
634
  const currentIndex = landmarks.indexOf(document.activeElement as HTMLElement);
579
- const nextIndex = currentIndex < landmarks.length - 1 ? currentIndex + 1 ;
635
+ const nextIndex = currentIndex < landmarks.length - 1 ? currentIndex + 1 : 0;
580
636
 
581
637
  if (landmarks[nextIndex]) {
582
638
  (landmarks[nextIndex] as HTMLElement).focus();
@@ -584,9 +640,10 @@ export class FocusNavigation {
584
640
  }
585
641
 
586
642
  // Navigate to previous landmark
587
- static focusPreviousLandmark()= Array.from(document.querySelectorAll('[role="banner"], [role="main"], [role="navigation"], [role="complementary"], [role="contentinfo"]'));
643
+ static focusPreviousLandmark(): void {
644
+ const landmarks = Array.from(document.querySelectorAll('[role="banner"], [role="main"], [role="navigation"], [role="complementary"], [role="contentinfo"]'));
588
645
  const currentIndex = landmarks.indexOf(document.activeElement as HTMLElement);
589
- const prevIndex = currentIndex > 0 ? currentIndex - 1 ;
646
+ const prevIndex = currentIndex > 0 ? currentIndex - 1 : landmarks.length - 1;
590
647
 
591
648
  if (landmarks[prevIndex]) {
592
649
  (landmarks[prevIndex] as HTMLElement).focus();
@@ -594,13 +651,14 @@ export class FocusNavigation {
594
651
  }
595
652
 
596
653
  // Focus first focusable element in container
597
- static focusFirstInContainer(container)= [
654
+ static focusFirstInContainer(container: HTMLElement): void {
655
+ const focusableSelectors = [
598
656
  'a[href]',
599
- 'button])',
600
- 'input])',
601
- 'select])',
602
- 'textarea])',
603
- '[tabindex]="-1"])'
657
+ 'button:not([disabled])',
658
+ 'input:not([disabled])',
659
+ 'select:not([disabled])',
660
+ 'textarea:not([disabled])',
661
+ '[tabindex]:not([tabindex="-1"])'
604
662
  ];
605
663
 
606
664
  const firstElement = container.querySelector(focusableSelectors.join(','));
@@ -610,13 +668,14 @@ export class FocusNavigation {
610
668
  }
611
669
 
612
670
  // Focus last focusable element in container
613
- static focusLastInContainer(container)= [
671
+ static focusLastInContainer(container: HTMLElement): void {
672
+ const focusableSelectors = [
614
673
  'a[href]',
615
- 'button])',
616
- 'input])',
617
- 'select])',
618
- 'textarea])',
619
- '[tabindex]="-1"])'
674
+ 'button:not([disabled])',
675
+ 'input:not([disabled])',
676
+ 'select:not([disabled])',
677
+ 'textarea:not([disabled])',
678
+ '[tabindex]:not([tabindex="-1"])'
620
679
  ];
621
680
 
622
681
  const elements = Array.from(container.querySelectorAll(focusableSelectors.join(',')));