@shohojdhara/atomix 0.4.8 → 0.5.0

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 (177) hide show
  1. package/atomix.config.ts +58 -1
  2. package/dist/atomix.css +148 -120
  3. package/dist/atomix.css.map +1 -1
  4. package/dist/atomix.min.css +1 -1
  5. package/dist/atomix.min.css.map +1 -1
  6. package/dist/charts.d.ts +33 -0
  7. package/dist/charts.js +1227 -122
  8. package/dist/charts.js.map +1 -1
  9. package/dist/core.d.ts +33 -10
  10. package/dist/core.js +1052 -41
  11. package/dist/core.js.map +1 -1
  12. package/dist/forms.d.ts +33 -0
  13. package/dist/forms.js +2086 -1035
  14. package/dist/forms.js.map +1 -1
  15. package/dist/heavy.d.ts +42 -1
  16. package/dist/heavy.js +1620 -600
  17. package/dist/heavy.js.map +1 -1
  18. package/dist/index.d.ts +441 -270
  19. package/dist/index.esm.js +1900 -638
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/index.js +1935 -670
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.min.js +1 -1
  24. package/dist/index.min.js.map +1 -1
  25. package/package.json +6 -3
  26. package/scripts/atomix-cli.js +148 -4
  27. package/scripts/cli/__tests__/basic.test.js +3 -2
  28. package/scripts/cli/__tests__/clean.test.js +278 -0
  29. package/scripts/cli/__tests__/component-validator.test.js +433 -0
  30. package/scripts/cli/__tests__/generator.test.js +613 -0
  31. package/scripts/cli/__tests__/glass-motion.test.js +256 -0
  32. package/scripts/cli/__tests__/integration.test.js +719 -108
  33. package/scripts/cli/__tests__/migrate.test.js +74 -0
  34. package/scripts/cli/__tests__/security.test.js +206 -0
  35. package/scripts/cli/__tests__/test-setup.js +3 -1
  36. package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
  37. package/scripts/cli/__tests__/token-provider.test.js +361 -0
  38. package/scripts/cli/__tests__/utils.test.js +5 -5
  39. package/scripts/cli/commands/benchmark.js +105 -0
  40. package/scripts/cli/commands/build-theme.js +4 -1
  41. package/scripts/cli/commands/clean.js +109 -0
  42. package/scripts/cli/commands/doctor.js +88 -0
  43. package/scripts/cli/commands/generate.js +135 -14
  44. package/scripts/cli/commands/init.js +45 -18
  45. package/scripts/cli/commands/migrate.js +106 -0
  46. package/scripts/cli/commands/sync-tokens.js +206 -0
  47. package/scripts/cli/commands/theme-bridge.js +248 -0
  48. package/scripts/cli/commands/tokens.js +157 -0
  49. package/scripts/cli/commands/validate.js +194 -0
  50. package/scripts/cli/internal/ai-engine.js +156 -0
  51. package/scripts/cli/internal/component-validator.js +443 -0
  52. package/scripts/cli/internal/config-loader.js +162 -0
  53. package/scripts/cli/internal/filesystem.js +102 -2
  54. package/scripts/cli/internal/generator.js +359 -39
  55. package/scripts/cli/internal/glass-generator.js +398 -0
  56. package/scripts/cli/internal/hook-generator.js +369 -0
  57. package/scripts/cli/internal/hooks.js +61 -0
  58. package/scripts/cli/internal/itcss-generator.js +565 -0
  59. package/scripts/cli/internal/motion-generator.js +679 -0
  60. package/scripts/cli/internal/template-engine.js +301 -0
  61. package/scripts/cli/internal/theme-bridge.js +664 -0
  62. package/scripts/cli/internal/tokens/engine.js +122 -0
  63. package/scripts/cli/internal/tokens/provider.js +34 -0
  64. package/scripts/cli/internal/tokens/providers/figma.js +50 -0
  65. package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
  66. package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
  67. package/scripts/cli/internal/tokens/token-provider.js +443 -0
  68. package/scripts/cli/internal/tokens/token-validator.js +513 -0
  69. package/scripts/cli/internal/validator.js +276 -0
  70. package/scripts/cli/internal/wizard.js +60 -6
  71. package/scripts/cli/mappings.js +23 -0
  72. package/scripts/cli/migration-tools.js +164 -94
  73. package/scripts/cli/plugins/style-dictionary.js +46 -0
  74. package/scripts/cli/templates/README.md +525 -95
  75. package/scripts/cli/templates/common-templates.js +40 -14
  76. package/scripts/cli/templates/components/react-component.ts +282 -0
  77. package/scripts/cli/templates/config/project-config.ts +112 -0
  78. package/scripts/cli/templates/hooks/use-component.ts +477 -0
  79. package/scripts/cli/templates/index.js +19 -4
  80. package/scripts/cli/templates/index.ts +171 -0
  81. package/scripts/cli/templates/next-templates.js +72 -0
  82. package/scripts/cli/templates/react-templates.js +70 -126
  83. package/scripts/cli/templates/scss-templates.js +35 -35
  84. package/scripts/cli/templates/stories/storybook-story.ts +241 -0
  85. package/scripts/cli/templates/styles/scss-component.ts +255 -0
  86. package/scripts/cli/templates/tests/vitest-test.ts +229 -0
  87. package/scripts/cli/templates/token-templates.js +337 -1
  88. package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
  89. package/scripts/cli/templates/types/component-types.ts +145 -0
  90. package/scripts/cli/templates/utils/testing-utils.ts +144 -0
  91. package/scripts/cli/templates/vanilla-templates.js +39 -0
  92. package/scripts/cli/token-manager.js +8 -2
  93. package/scripts/cli/utils/cache-manager.js +240 -0
  94. package/scripts/cli/utils/detector.js +46 -0
  95. package/scripts/cli/utils/diagnostics.js +289 -0
  96. package/scripts/cli/utils/error.js +45 -3
  97. package/scripts/cli/utils/helpers.js +24 -0
  98. package/scripts/cli/utils/logger.js +1 -1
  99. package/scripts/cli/utils/security.js +302 -0
  100. package/scripts/cli/utils/telemetry.js +115 -0
  101. package/scripts/cli/utils/validation.js +4 -38
  102. package/scripts/cli/utils.js +46 -0
  103. package/src/components/Accordion/Accordion.stories.tsx +0 -18
  104. package/src/components/Accordion/Accordion.test.tsx +0 -17
  105. package/src/components/Accordion/Accordion.tsx +0 -4
  106. package/src/components/AtomixGlass/AtomixGlass.tsx +102 -2
  107. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +125 -12
  108. package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
  109. package/src/components/AtomixGlass/README.md +25 -10
  110. package/src/components/AtomixGlass/animation-system.ts +578 -0
  111. package/src/components/AtomixGlass/shader-utils.ts +3 -0
  112. package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +653 -0
  113. package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +95 -0
  114. package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +212 -0
  115. package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +348 -0
  116. package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +410 -0
  117. package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +436 -0
  118. package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +264 -0
  119. package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +247 -0
  120. package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +418 -0
  121. package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +402 -0
  122. package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
  123. package/src/components/AtomixGlass/stories/Playground.stories.tsx +658 -93
  124. package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +335 -0
  125. package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +441 -0
  126. package/src/components/AtomixGlass/stories/argTypes.ts +384 -0
  127. package/src/components/AtomixGlass/stories/shared-components.tsx +91 -1
  128. package/src/components/AtomixGlass/stories/types.ts +127 -0
  129. package/src/components/Avatar/Avatar.tsx +1 -1
  130. package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
  131. package/src/components/Button/Button.stories.tsx +10 -0
  132. package/src/components/Button/Button.test.tsx +16 -11
  133. package/src/components/Button/Button.tsx +4 -4
  134. package/src/components/Card/Card.tsx +1 -1
  135. package/src/components/Dropdown/Dropdown.tsx +12 -12
  136. package/src/components/Form/Select.tsx +62 -3
  137. package/src/components/Modal/Modal.tsx +14 -3
  138. package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
  139. package/src/components/Slider/Slider.stories.tsx +3 -3
  140. package/src/components/Slider/Slider.tsx +38 -0
  141. package/src/components/Steps/Steps.tsx +3 -3
  142. package/src/components/Tabs/Tabs.tsx +77 -8
  143. package/src/components/Testimonial/Testimonial.tsx +1 -1
  144. package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
  145. package/src/components/TypedButton/TypedButton.tsx +39 -0
  146. package/src/components/TypedButton/index.ts +2 -0
  147. package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
  148. package/src/lib/composables/index.ts +4 -7
  149. package/src/lib/composables/types.ts +45 -0
  150. package/src/lib/composables/useAccordion.ts +0 -7
  151. package/src/lib/composables/useAtomixGlass.ts +144 -5
  152. package/src/lib/composables/useChartExport.ts +3 -13
  153. package/src/lib/composables/useDropdown.ts +66 -0
  154. package/src/lib/composables/useFocusTrap.ts +80 -0
  155. package/src/lib/composables/usePerformanceMonitor.ts +448 -0
  156. package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
  157. package/src/lib/composables/useResponsiveGlass.ts +441 -0
  158. package/src/lib/composables/useTooltip.ts +16 -0
  159. package/src/lib/composables/useTypedButton.ts +66 -0
  160. package/src/lib/config/index.ts +62 -5
  161. package/src/lib/constants/components.ts +55 -0
  162. package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
  163. package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
  164. package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
  165. package/src/lib/types/components.ts +37 -11
  166. package/src/lib/types/glass.ts +35 -0
  167. package/src/lib/types/index.ts +1 -0
  168. package/src/lib/utils/displacement-generator.ts +1 -1
  169. package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
  170. package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
  171. package/src/styles/06-components/_components.testbutton.scss +212 -0
  172. package/src/styles/06-components/_components.testtypecheck.scss +212 -0
  173. package/src/styles/06-components/_components.typedbutton.scss +212 -0
  174. package/src/styles/99-utilities/_index.scss +1 -0
  175. package/src/styles/99-utilities/_utilities.text.scss +1 -1
  176. package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
  177. package/src/styles/06-components/old.chart.styles.scss +0 -2788
@@ -0,0 +1,255 @@
1
+ /**
2
+ * SCSS Component Templates
3
+ * Templates for generating SCSS styles following ITCSS methodology
4
+ */
5
+
6
+ /**
7
+ * Generates a complete SCSS component file following ITCSS and BEM
8
+ */
9
+ export const scssComponentTemplate = (name: string): string => {
10
+ const componentName = name.toLowerCase();
11
+
12
+ return `@use '../01-settings/settings.config' as config;
13
+ @use '../01-settings/settings.${componentName}' as ${componentName};
14
+ @use '../01-settings/settings.colors' as colors;
15
+ @use '../01-settings/settings.design-tokens' as color-maps;
16
+ @use '../01-settings/settings.border-radius' as border-radius;
17
+ @use '../02-tools/tools.border-radius' as *;
18
+ @use '../02-tools/tools.rem' as *;
19
+ @use '../02-tools/tools.background' as *;
20
+ @use '../02-tools/tools.color-functions' as *;
21
+
22
+ .c-${componentName} {
23
+ $root: &;
24
+
25
+ // Component CSS Custom Properties
26
+ --#{config.$prefix}${componentName}-padding-x: #{${componentName}.$${componentName}-padding-x};
27
+ --#{config.$prefix}${componentName}-padding-y: #{${componentName}.$${componentName}-padding-y};
28
+ --#{config.$prefix}${componentName}-gap: #{${componentName}.$${componentName}-gap};
29
+ --#{config.$prefix}${componentName}-font-family: #{${componentName}.$${componentName}-font-family};
30
+ --#{config.$prefix}${componentName}-font-size: #{${componentName}.$${componentName}-font-size};
31
+ --#{config.$prefix}${componentName}-font-weight: #{${componentName}.$${componentName}-font-weight};
32
+ --#{config.$prefix}${componentName}-line-height: #{${componentName}.$${componentName}-line-height};
33
+ --#{config.$prefix}${componentName}-color: #{${componentName}.$${componentName}-color};
34
+ --#{config.$prefix}${componentName}-bg: #{${componentName}.$${componentName}-bg};
35
+ --#{config.$prefix}${componentName}-border-width: #{${componentName}.$${componentName}-border-width};
36
+ --#{config.$prefix}${componentName}-border-color: #{${componentName}.$${componentName}-border-color};
37
+ --#{config.$prefix}${componentName}-border-radius: #{${componentName}.$${componentName}-border-radius};
38
+ --#{config.$prefix}${componentName}-transition: #{${componentName}.$${componentName}-transition};
39
+ --#{config.$prefix}${componentName}-disabled-opacity: #{${componentName}.$${componentName}-disabled-opacity};
40
+
41
+ // Base component styles
42
+ display: inline-flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ gap: var(--#{config.$prefix}${componentName}-gap);
46
+ padding: var(--#{config.$prefix}${componentName}-padding-y) var(--#{config.$prefix}${componentName}-padding-x);
47
+ font-family: var(--#{config.$prefix}${componentName}-font-family);
48
+ font-size: var(--#{config.$prefix}${componentName}-font-size);
49
+ font-weight: var(--#{config.$prefix}${componentName}-font-weight);
50
+ line-height: var(--#{config.$prefix}${componentName}-line-height);
51
+ color: var(--#{config.$prefix}${componentName}-color);
52
+ background: var(--#{config.$prefix}${componentName}-bg);
53
+ border: var(--#{config.$prefix}${componentName}-border-width) solid var(--#{config.$prefix}${componentName}-border-color);
54
+ border-radius: var(--#{config.$prefix}${componentName}-border-radius);
55
+ transition: var(--#{config.$prefix}${componentName}-transition);
56
+ cursor: pointer;
57
+
58
+ // Size variants
59
+ &--sm {
60
+ --#{config.$prefix}${componentName}-padding-x: #{${componentName}.$${componentName}-sm-padding-x};
61
+ --#{config.$prefix}${componentName}-padding-y: #{${componentName}.$${componentName}-sm-padding-y};
62
+ --#{config.$prefix}${componentName}-font-size: #{${componentName}.$${componentName}-sm-font-size};
63
+ }
64
+
65
+ &--lg {
66
+ --#{config.$prefix}${componentName}-padding-x: #{${componentName}.$${componentName}-lg-padding-x};
67
+ --#{config.$prefix}${componentName}-padding-y: #{${componentName}.$${componentName}-lg-padding-y};
68
+ --#{config.$prefix}${componentName}-font-size: #{${componentName}.$${componentName}-lg-font-size};
69
+ }
70
+
71
+ // Color variants
72
+ &--primary {
73
+ --#{config.$prefix}${componentName}-color: #{${componentName}.$${componentName}-primary-color};
74
+ --#{config.$prefix}${componentName}-bg: #{${componentName}.$${componentName}-primary-bg};
75
+ --#{config.$prefix}${componentName}-border-color: #{${componentName}.$${componentName}-primary-border};
76
+ }
77
+
78
+ &--secondary {
79
+ --#{config.$prefix}${componentName}-color: #{${componentName}.$${componentName}-secondary-color};
80
+ --#{config.$prefix}${componentName}-bg: #{${componentName}.$${componentName}-secondary-bg};
81
+ --#{config.$prefix}${componentName}-border-color: #{${componentName}.$${componentName}-secondary-border};
82
+ }
83
+
84
+ // Interactive states
85
+ &:hover {
86
+ @if ${componentName}.$${componentName}-enable-hover {
87
+ background: tint(var(--#{config.$prefix}${componentName}-bg), 10%);
88
+ border-color: tint(var(--#{config.$prefix}${componentName}-border-color), 15%);
89
+ }
90
+ }
91
+
92
+ &:focus {
93
+ outline: 2px solid var(--atomix-focus-color);
94
+ outline-offset: 2px;
95
+ }
96
+
97
+ &:active {
98
+ background: shade(var(--#{config.$prefix}${componentName}-bg), 10%);
99
+ }
100
+
101
+ // Disabled state
102
+ &.is-disabled,
103
+ &[aria-disabled="true"] {
104
+ opacity: var(--#{config.$prefix}${componentName}-disabled-opacity);
105
+ cursor: not-allowed;
106
+ pointer-events: none;
107
+ }
108
+
109
+ // Glass variant (auto-generated from glass-generator)
110
+ &--glass {
111
+ background: var(--#{config.$prefix}${componentName}-glass-bg, rgba(255, 255, 255, 0.1));
112
+ backdrop-filter: var(--#{config.$prefix}${componentName}-glass-backdrop, blur(10px) saturate(200%));
113
+ border-color: var(--#{config.$prefix}${componentName}-glass-border, rgba(255, 255, 255, 0.2));
114
+
115
+ @media (prefers-reduced-transparency: reduce) {
116
+ background: var(--#{config.$prefix}${componentName}-glass-fallback, rgba(255, 255, 255, 0.8));
117
+ backdrop-filter: none;
118
+ }
119
+
120
+ &:hover:not(:disabled) {
121
+ background: var(--#{config.$prefix}${componentName}-glass-hover, rgba(255, 255, 255, 0.15));
122
+ }
123
+ }
124
+
125
+ // Animation variants (auto-generated from motion-generator)
126
+ &--animate-fade-in {
127
+ animation: atomix-fade-in var(--atomix-duration-base) var(--atomix-easing-smooth);
128
+ }
129
+
130
+ &--animate-slide-in-up {
131
+ animation: atomix-slide-in-up var(--atomix-duration-slow) var(--atomix-easing-smooth);
132
+ }
133
+
134
+ &--animate-scale-in {
135
+ animation: atomix-scale-in var(--atomix-duration-base) var(--atomix-easing-smooth);
136
+ }
137
+
138
+ &--animate-pulse {
139
+ animation: atomix-pulse 2s var(--atomix-easing-smooth) infinite;
140
+ }
141
+
142
+ &--animate-shimmer {
143
+ animation: atomix-shimmer 2s linear infinite;
144
+ background: linear-gradient(
145
+ 90deg,
146
+ var(--atomix-color-neutral-100) 0%,
147
+ var(--atomix-color-neutral-200) 50%,
148
+ var(--atomix-color-neutral-100) 100%
149
+ );
150
+ background-size: 200% 100%;
151
+ }
152
+
153
+ // Motion preferences - reduced motion
154
+ @media (prefers-reduced-motion: reduce) {
155
+ &,
156
+ * {
157
+ animation-duration: 0.01ms !important;
158
+ animation-iteration-count: 1 !important;
159
+ transition-duration: 0.01ms !important;
160
+ }
161
+ }
162
+
163
+ // Data states
164
+ &[data-state="open"] {
165
+ // Open state styles
166
+ }
167
+
168
+ &[data-state="closed"] {
169
+ // Closed state styles
170
+ }
171
+ }
172
+ `;
173
+ };
174
+
175
+ /**
176
+ * Generates SCSS settings file for a component
177
+ */
178
+ export const scssSettingsTemplate = (name: string): string => {
179
+ const componentName = name.toLowerCase();
180
+
181
+ return `// ${name} Component Settings
182
+ // Located in src/styles/01-settings/_settings.${componentName}.scss
183
+
184
+ @use 'sass:map';
185
+ @use 'settings.colors' as *;
186
+ @use 'settings.spacing' as spacing;
187
+ @use 'settings.border-radius' as *;
188
+ @use 'settings.typography' as *;
189
+ @use '../02-tools/tools.color-functions' as *;
190
+
191
+ // Component-specific variables
192
+ $${componentName}-padding-x: map.get(spacing.$spacing-sizes, 3) !default;
193
+ $${componentName}-padding-y: map.get(spacing.$spacing-sizes, 2) !default;
194
+ $${componentName}-gap: map.get(spacing.$spacing-sizes, 2) !default;
195
+ $${componentName}-font-family: $font-family-base !default;
196
+ $${componentName}-font-size: $font-size-base !default;
197
+ $${componentName}-font-weight: $font-weight-normal !default;
198
+ $${componentName}-line-height: $line-height-base !default;
199
+ $${componentName}-color: $text-primary !default;
200
+ $${componentName}-bg: $surface !default;
201
+ $${componentName}-border-width: 1px !default;
202
+ $${componentName}-border-color: $border-default !default;
203
+ $${componentName}-border-radius: $border-radius-md !default;
204
+ $${componentName}-transition: all 0.2s ease !default;
205
+ $${componentName}-disabled-opacity: 0.6 !default;
206
+ $${componentName}-enable-hover: true !default;
207
+
208
+ // Size variants
209
+ $${componentName}-sm-padding-x: map.get(spacing.$spacing-sizes, 2) !default;
210
+ $${componentName}-sm-padding-y: map.get(spacing.$spacing-sizes, 1) !default;
211
+ $${componentName}-sm-font-size: $font-size-sm !default;
212
+
213
+ $${componentName}-lg-padding-x: map.get(spacing.$spacing-sizes, 4) !default;
214
+ $${componentName}-lg-padding-y: map.get(spacing.$spacing-sizes, 3) !default;
215
+ $${componentName}-lg-font-size: $font-size-lg !default;
216
+
217
+ // Color variants
218
+ $${componentName}-primary-bg: $primary !default;
219
+ $${componentName}-primary-color: color-contrast($primary) !default;
220
+ $${componentName}-primary-border: shade($primary, 10%) !default;
221
+
222
+ $${componentName}-secondary-bg: $secondary !default;
223
+ $${componentName}-secondary-color: color-contrast($secondary) !default;
224
+ $${componentName}-secondary-border: shade($secondary, 10%) !default;
225
+
226
+ // Glass variant
227
+ $${componentName}-glass-bg: rgba(255, 255, 255, 0.1) !default;
228
+ $${componentName}-glass-border: rgba(255, 255, 255, 0.2) !default;
229
+ $${componentName}-glass-backdrop: blur(10px) !default;
230
+ `;
231
+ };
232
+
233
+ /**
234
+ * Combines both component and settings templates
235
+ */
236
+ export const scssTemplate = (name: string) => {
237
+ return {
238
+ component: scssComponentTemplate(name),
239
+ settings: scssSettingsTemplate(name),
240
+ };
241
+ };
242
+
243
+ /**
244
+ * All SCSS component templates
245
+ */
246
+ export const scssComponentTemplates = {
247
+ component: scssComponentTemplate,
248
+ settings: scssSettingsTemplate,
249
+ full: scssTemplate,
250
+ };
251
+
252
+ /**
253
+ * Type for SCSS component templates object
254
+ */
255
+ export type ScssComponentTemplates = typeof scssComponentTemplates;
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Vitest Test Templates
3
+ * Templates for generating comprehensive component tests with accessibility
4
+ */
5
+
6
+ /**
7
+ * Generates a comprehensive Vitest test suite with accessibility testing
8
+ */
9
+ export const testTemplate = (name: string): string => `import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10
+ import { render, screen, fireEvent, act } from '@testing-library/react';
11
+ import { axe, toHaveNoViolations } from 'jest-axe';
12
+ import { ${name} } from './${name}';
13
+
14
+ // Extend Vitest matchers
15
+ expect.extend(toHaveNoViolations);
16
+
17
+ // Mock IntersectionObserver
18
+ global.IntersectionObserver = vi.fn(() => ({
19
+ observe: vi.fn(),
20
+ unobserve: vi.fn(),
21
+ disconnect: vi.fn()
22
+ }));
23
+
24
+ // Mock ResizeObserver
25
+ global.ResizeObserver = vi.fn().mockImplementation(() => ({
26
+ observe: vi.fn(),
27
+ unobserve: vi.fn(),
28
+ disconnect: vi.fn()
29
+ }));
30
+
31
+ describe('${name}', () => {
32
+ // Accessibility Tests
33
+ describe('Accessibility', () => {
34
+ it('should have no accessibility violations', async () => {
35
+ const { container } = render(<${name}>Accessible Content</${name}>);
36
+ const results = await axe(container);
37
+ expect(results).toHaveNoViolations();
38
+ });
39
+
40
+ it('should have proper aria attributes', () => {
41
+ render(<${name} aria-label="Test component">Content</${name}>);
42
+ const element = screen.getByLabelText('Test component');
43
+ expect(element).toBeInTheDocument();
44
+ });
45
+
46
+ it('should support keyboard navigation', () => {
47
+ render(<${name}>Focusable Content</${name}>);
48
+ const element = screen.getByText('Focusable Content');
49
+ element.focus();
50
+ expect(element).toHaveFocus();
51
+ });
52
+ });
53
+
54
+ // Rendering Tests
55
+ describe('Rendering', () => {
56
+ it('renders children correctly', () => {
57
+ render(<${name}>Test Content</${name}>);
58
+ expect(screen.getByText('Test Content')).toBeInTheDocument();
59
+ });
60
+
61
+ it('applies className prop', () => {
62
+ const { container } = render(<${name} className="custom-class">Content</${name}>);
63
+ const element = container.firstChild;
64
+ expect(element).toHaveClass('custom-class');
65
+ });
66
+
67
+ it('renders with custom attributes', () => {
68
+ render(<${name} data-testid="test-${name.toLowerCase()}">Content</${name}>);
69
+ expect(screen.getByTestId('test-${name.toLowerCase()}')).toBeInTheDocument();
70
+ });
71
+ });
72
+
73
+ // Props Tests
74
+ describe('Props', () => {
75
+ it('applies size variant classes', () => {
76
+ const { container } = render(<${name} size="lg">Content</${name}>);
77
+ const element = container.firstChild;
78
+ expect(element).toHaveClass('c-${name.toLowerCase()}--lg');
79
+ });
80
+
81
+ it('handles disabled state', () => {
82
+ const { container } = render(<${name} disabled>Content</${name}>);
83
+ const element = container.firstChild;
84
+ expect(element).toHaveAttribute('aria-disabled', 'true');
85
+ expect(element).toHaveClass('is-disabled');
86
+ });
87
+
88
+ it('passes through data attributes', () => {
89
+ const { container } = render(<${name} data-custom="value">Content</${name}>);
90
+ const element = container.firstChild;
91
+ expect(element).toHaveAttribute('data-custom', 'value');
92
+ });
93
+ });
94
+
95
+ // Event Handling Tests
96
+ describe('Event Handling', () => {
97
+ it('calls onClick handler when clicked', () => {
98
+ const handleClick = vi.fn();
99
+ render(<${name} onClick={handleClick}>Clickable</${name}>);
100
+
101
+ fireEvent.click(screen.getByText('Clickable'));
102
+ expect(handleClick).toHaveBeenCalledTimes(1);
103
+ });
104
+
105
+ it('does not call onClick when disabled', () => {
106
+ const handleClick = vi.fn();
107
+ render(<${name} onClick={handleClick} disabled>Disabled</${name}>);
108
+
109
+ fireEvent.click(screen.getByText('Disabled'));
110
+ expect(handleClick).not.toHaveBeenCalled();
111
+ });
112
+
113
+ it('handles mouse events', () => {
114
+ const handleMouseEnter = vi.fn();
115
+ const handleMouseLeave = vi.fn();
116
+
117
+ render(
118
+ <${name}
119
+ onMouseEnter={handleMouseEnter}
120
+ onMouseLeave={handleMouseLeave}
121
+ >
122
+ Hoverable
123
+ </${name}>
124
+ );
125
+
126
+ const element = screen.getByText('Hoverable');
127
+ fireEvent.mouseEnter(element);
128
+ fireEvent.mouseLeave(element);
129
+
130
+ expect(handleMouseEnter).toHaveBeenCalledTimes(1);
131
+ expect(handleMouseLeave).toHaveBeenCalledTimes(1);
132
+ });
133
+ });
134
+
135
+ // Ref Forwarding Tests
136
+ describe('Ref Forwarding', () => {
137
+ it('forwards ref correctly', () => {
138
+ const ref = React.createRef<HTMLDivElement>();
139
+ render(<${name} ref={ref}>Content</${name}>);
140
+ expect(ref.current).toBeInstanceOf(HTMLDivElement);
141
+ });
142
+
143
+ it('allows imperative methods access', () => {
144
+ const ref = React.createRef<{ focus: () => void }>();
145
+ render(<${name} ref={ref}>Focusable</${name}>);
146
+
147
+ // Assuming component exposes focus method
148
+ if (ref.current && ref.current.focus) {
149
+ const spy = vi.spyOn(ref.current, 'focus');
150
+ ref.current.focus();
151
+ expect(spy).toHaveBeenCalled();
152
+ }
153
+ });
154
+ });
155
+
156
+ // Performance Tests
157
+ describe('Performance', () => {
158
+ it('renders efficiently without unnecessary re-renders', () => {
159
+ const renderSpy = vi.fn();
160
+ const TestWrapper = () => {
161
+ renderSpy();
162
+ return <${name}>Performance Test</${name}>;
163
+ };
164
+
165
+ render(<TestWrapper />);
166
+ expect(renderSpy).toHaveBeenCalledTimes(1);
167
+ });
168
+ });
169
+
170
+ // Edge Cases
171
+ describe('Edge Cases', () => {
172
+ it('handles empty children gracefully', () => {
173
+ const { container } = render(<${name}></${name}>);
174
+ expect(container.firstChild).toBeInTheDocument();
175
+ });
176
+
177
+ it('handles null children', () => {
178
+ const { container } = render(<${name}>{null}</${name}>);
179
+ expect(container.firstChild).toBeInTheDocument();
180
+ });
181
+
182
+ it('handles undefined props', () => {
183
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
184
+
185
+ expect(() => {
186
+ render(<${name} size={undefined}>Content</${name}>);
187
+ }).not.toThrow();
188
+
189
+ consoleSpy.mockRestore();
190
+ });
191
+ });
192
+
193
+ // Async Behavior Tests
194
+ describe('Async Behavior', () => {
195
+ it('handles async state changes', async () => {
196
+ const AsyncComponent = () => {
197
+ const [loaded, setLoaded] = React.useState(false);
198
+
199
+ React.useEffect(() => {
200
+ setTimeout(() => setLoaded(true), 100);
201
+ }, []);
202
+
203
+ return <${name}>{loaded ? 'Loaded' : 'Loading...'}</${name}>;
204
+ };
205
+
206
+ render(<AsyncComponent />);
207
+ expect(screen.getByText('Loading...')).toBeInTheDocument();
208
+
209
+ await act(async () => {
210
+ await new Promise(resolve => setTimeout(resolve, 150));
211
+ });
212
+
213
+ expect(screen.getByText('Loaded')).toBeInTheDocument();
214
+ });
215
+ });
216
+ });
217
+ `;
218
+
219
+ /**
220
+ * All Vitest test templates
221
+ */
222
+ export const vitestTestTemplates = {
223
+ test: testTemplate,
224
+ };
225
+
226
+ /**
227
+ * Type for Vitest test templates object
228
+ */
229
+ export type VitestTestTemplates = typeof vitestTestTemplates;