@shohojdhara/atomix 0.4.8 → 0.4.9

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 (165) 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 +4 -1
  112. package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
  113. package/src/components/AtomixGlass/stories/Phase1-Animation.stories.tsx +653 -0
  114. package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +95 -0
  115. package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -51
  116. package/src/components/AtomixGlass/stories/shared-components.tsx +6 -0
  117. package/src/components/Avatar/Avatar.tsx +1 -1
  118. package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
  119. package/src/components/Button/Button.stories.tsx +10 -0
  120. package/src/components/Button/Button.test.tsx +16 -11
  121. package/src/components/Button/Button.tsx +4 -4
  122. package/src/components/Card/Card.tsx +1 -1
  123. package/src/components/Dropdown/Dropdown.tsx +12 -12
  124. package/src/components/Form/Select.tsx +62 -3
  125. package/src/components/Modal/Modal.tsx +14 -3
  126. package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
  127. package/src/components/Slider/Slider.stories.tsx +3 -3
  128. package/src/components/Slider/Slider.tsx +38 -0
  129. package/src/components/Steps/Steps.tsx +3 -3
  130. package/src/components/Tabs/Tabs.tsx +77 -8
  131. package/src/components/Testimonial/Testimonial.tsx +1 -1
  132. package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
  133. package/src/components/TypedButton/TypedButton.tsx +39 -0
  134. package/src/components/TypedButton/index.ts +2 -0
  135. package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
  136. package/src/lib/composables/index.ts +4 -7
  137. package/src/lib/composables/types.ts +45 -0
  138. package/src/lib/composables/useAccordion.ts +0 -7
  139. package/src/lib/composables/useAtomixGlass.ts +144 -5
  140. package/src/lib/composables/useChartExport.ts +3 -13
  141. package/src/lib/composables/useDropdown.ts +66 -0
  142. package/src/lib/composables/useFocusTrap.ts +80 -0
  143. package/src/lib/composables/usePerformanceMonitor.ts +448 -0
  144. package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
  145. package/src/lib/composables/useResponsiveGlass.ts +441 -0
  146. package/src/lib/composables/useTooltip.ts +16 -0
  147. package/src/lib/composables/useTypedButton.ts +66 -0
  148. package/src/lib/config/index.ts +62 -5
  149. package/src/lib/constants/components.ts +55 -0
  150. package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
  151. package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
  152. package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
  153. package/src/lib/types/components.ts +37 -11
  154. package/src/lib/types/glass.ts +35 -0
  155. package/src/lib/types/index.ts +1 -0
  156. package/src/lib/utils/displacement-generator.ts +1 -1
  157. package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
  158. package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
  159. package/src/styles/06-components/_components.testbutton.scss +212 -0
  160. package/src/styles/06-components/_components.testtypecheck.scss +212 -0
  161. package/src/styles/06-components/_components.typedbutton.scss +212 -0
  162. package/src/styles/99-utilities/_index.scss +1 -0
  163. package/src/styles/99-utilities/_utilities.text.scss +1 -1
  164. package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
  165. package/src/styles/06-components/old.chart.styles.scss +0 -2788
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Atomix CLI Validate Command
3
+ * Standalone audit tool for code and configuration quality
4
+ */
5
+
6
+ import { logger } from '../utils/logger.js';
7
+ import { validateA11y, validateTokens, validatePerformance, validateComponent } from '../internal/validator.js';
8
+ import { validateComponentName } from '../utils/validation.js';
9
+ import { hookManager } from '../internal/hooks.js';
10
+ import { telemetry } from '../utils/telemetry.js';
11
+ import { AtomixCLIError, ErrorCategory } from '../utils/error.js';
12
+ import chalk from 'chalk';
13
+
14
+ /**
15
+ * Action for the `atomix validate` command
16
+ * @param {object} options - Command options
17
+ * @param {string} [subcommand] - When 'component', run component-scoped validation
18
+ * @param {string} [name] - Component name for validate component <name>
19
+ */
20
+ export async function validateAction(options = {}, subcommand, name) {
21
+ if (subcommand === 'component' && name) {
22
+ return runComponentValidation(name);
23
+ }
24
+
25
+ const spinner = logger.spinner('Starting validation audit...').start();
26
+
27
+ try {
28
+ const a11yResults = await validateA11y();
29
+ const tokenResults = await validateTokens();
30
+ const performanceResults = await validatePerformance();
31
+
32
+ // Phase 4: CLI Performance Budget check
33
+ const telemetryLogs = await telemetry.getLogs();
34
+ const cliPerformanceIssues = validateCLIPerformance(telemetryLogs);
35
+
36
+ spinner.stop();
37
+
38
+ // Collect all results into a unified report
39
+ let report = {
40
+ valid: true,
41
+ issues: [],
42
+ rawResults: {
43
+ a11y: a11yResults,
44
+ tokens: tokenResults,
45
+ performance: performanceResults,
46
+ cli: cliPerformanceIssues
47
+ }
48
+ };
49
+
50
+ // Populate initial issues from standard validators
51
+ const allResults = [...a11yResults, ...tokenResults, ...performanceResults, ...cliPerformanceIssues];
52
+ for (const res of allResults) {
53
+ report.issues.push({
54
+ type: res.type,
55
+ severity: res.severity,
56
+ file: res.file,
57
+ message: res.message
58
+ });
59
+ if (res.severity === 'error') report.valid = false;
60
+ }
61
+
62
+ // Trigger plugin hooks for custom validation
63
+ report = await hookManager.trigger('onValidate', report);
64
+
65
+ logger.box('Atomix Quality Audit', {
66
+ borderColor: 'magenta',
67
+ padding: 1,
68
+ margin: 1
69
+ });
70
+
71
+ if (report.issues.length === 0 && report.valid) {
72
+ console.log(chalk.bold.green('✨ No issues found! Your project meets all quality criteria.'));
73
+ return;
74
+ }
75
+
76
+ let errors = 0;
77
+ let warnings = 0;
78
+
79
+ for (const result of report.issues) {
80
+ // Handle both object-based issues (standard) and string-based issues (simple plugin hooks)
81
+ const isObject = typeof result === 'object';
82
+ const severity = isObject ? (result.severity || 'error') : 'error';
83
+ const type = isObject ? (result.type || 'PLUGIN') : 'PLUGIN';
84
+ const file = isObject ? (result.file || 'N/A') : 'N/A';
85
+ const message = isObject ? result.message : result;
86
+
87
+ const icon = severity === 'error' ? chalk.red('❌') : chalk.yellow('⚠️');
88
+ if (severity === 'error') errors++;
89
+ else warnings++;
90
+
91
+ console.log(`${icon} [${type.toUpperCase()}] ${chalk.bold(file)}: ${message}`);
92
+ }
93
+
94
+ console.log(chalk.bold(`\nSummary: ${errors} errors, ${warnings} warnings.`));
95
+
96
+ if (errors > 0) {
97
+ throw new AtomixCLIError(
98
+ `Validation failed with ${errors} error(s) and ${warnings} warning(s).`,
99
+ ErrorCategory.VALIDATION,
100
+ ['Fix the reported issues and run atomix validate again.']
101
+ );
102
+ }
103
+ } catch (error) {
104
+ spinner.fail('Validation failed');
105
+ throw error;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Validate CLI performance against a budget
111
+ */
112
+ function validateCLIPerformance(logs) {
113
+ if (logs.length === 0) return [];
114
+
115
+ const issues = [];
116
+ const BUDGET_MS = 2000;
117
+ const byCommand = {};
118
+
119
+ logs.forEach(log => {
120
+ if (!byCommand[log.command]) {
121
+ byCommand[log.command] = { durations: [] };
122
+ }
123
+ byCommand[log.command].durations.push(log.duration);
124
+ });
125
+
126
+ for (const [name, data] of Object.entries(byCommand)) {
127
+ data.durations.sort((a, b) => a - b);
128
+ const p95Index = Math.floor(data.durations.length * 0.95);
129
+ const p95 = data.durations[p95Index];
130
+
131
+ if (p95 > BUDGET_MS) {
132
+ issues.push({
133
+ type: 'performance',
134
+ severity: 'warning',
135
+ file: `cli:${name}`,
136
+ message: `CLI Performance budget exceeded (P95: ${p95}ms, Budget: ${BUDGET_MS}ms)`
137
+ });
138
+ }
139
+ }
140
+
141
+ return issues;
142
+ }
143
+
144
+ /**
145
+ * Run validation for a single component and print component-scoped report
146
+ * @param {string} name - Component name (PascalCase)
147
+ */
148
+ async function runComponentValidation(name) {
149
+ const nameValidation = await validateComponentName(name);
150
+ if (!nameValidation.isValid) {
151
+ throw new AtomixCLIError(
152
+ nameValidation.error || `Invalid component name: ${name}`,
153
+ ErrorCategory.VALIDATION,
154
+ ['Use PascalCase (e.g. Button, Card). See atomix validate --help.']
155
+ );
156
+ }
157
+
158
+ const spinner = logger.spinner(`Validating component ${name}...`).start();
159
+ try {
160
+ const report = await validateComponent(name);
161
+ spinner.stop();
162
+
163
+ logger.box(`Component: ${report.component}`, {
164
+ borderColor: 'magenta',
165
+ padding: 1,
166
+ margin: 1
167
+ });
168
+
169
+ if (report.issues.length === 0) {
170
+ console.log(chalk.bold.green(`✨ No issues found for ${report.component}.`));
171
+ return;
172
+ }
173
+
174
+ let errors = 0;
175
+ let warnings = 0;
176
+ for (const r of report.issues) {
177
+ const icon = r.severity === 'error' ? chalk.red('❌') : chalk.yellow('⚠️');
178
+ if (r.severity === 'error') errors++;
179
+ else warnings++;
180
+ console.log(`${icon} [${r.type}] ${chalk.bold(r.file)}: ${r.message}`);
181
+ }
182
+ console.log(chalk.bold(`\nSummary: ${errors} errors, ${warnings} warnings.`));
183
+ if (!report.valid) {
184
+ throw new AtomixCLIError(
185
+ `Component validation failed with ${errors} error(s) and ${warnings} warning(s).`,
186
+ ErrorCategory.VALIDATION,
187
+ ['Fix the reported issues and run atomix validate component <Name> again.']
188
+ );
189
+ }
190
+ } catch (error) {
191
+ spinner.fail('Validation failed');
192
+ throw error;
193
+ }
194
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Atomix CLI - AI Engine
3
+ * Handles integration with LLMs for component generation
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import { logger } from '../utils/logger.js';
8
+ import { configLoader } from './config-loader.js';
9
+
10
+ /**
11
+ * AI Scaffolding Engine
12
+ */
13
+ export class AIEngine {
14
+ constructor() {
15
+ this.config = configLoader.get('ai') || {};
16
+ }
17
+
18
+ /**
19
+ * Generate component code based on prompt
20
+ */
21
+ async generateComponent(name, prompt) {
22
+ const provider = this.config.provider || 'openai';
23
+ const apiKey = this.config.apiKey || process.env.ATOMIX_AI_API_KEY;
24
+
25
+ if (!apiKey) {
26
+ throw new Error(`AI API Key missing. Please configure it in atomix.config.ts or set ATOMIX_AI_API_KEY environment variable.`);
27
+ }
28
+
29
+ logger.info(chalk.blue(`🤖 AI Engine: Generating component "${name}" using ${provider}...`));
30
+
31
+ try {
32
+ let response;
33
+ if (provider === 'openai') {
34
+ response = await this.callOpenAI(name, prompt, apiKey);
35
+ } else if (provider === 'anthropic') {
36
+ response = await this.callAnthropic(name, prompt, apiKey);
37
+ } else {
38
+ throw new Error(`Unsupported AI provider: ${provider}`);
39
+ }
40
+
41
+ return this.parseAIResponse(response);
42
+ } catch (error) {
43
+ logger.error(`AI Generation failed: ${error.message}`);
44
+ throw error;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Call OpenAI API
50
+ */
51
+ async callOpenAI(name, prompt, apiKey) {
52
+ const model = this.config.model || 'gpt-4';
53
+ const systemPrompt = this.getSystemPrompt(name);
54
+
55
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
56
+ method: 'POST',
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ 'Authorization': `Bearer ${apiKey}`
60
+ },
61
+ body: JSON.stringify({
62
+ model: model,
63
+ messages: [
64
+ { role: 'system', content: systemPrompt },
65
+ { role: 'user', content: prompt }
66
+ ],
67
+ temperature: 0.7
68
+ })
69
+ });
70
+
71
+ if (!response.ok) {
72
+ const errorData = await response.json();
73
+ throw new Error(`OpenAI API error: ${errorData.error?.message || response.statusText}`);
74
+ }
75
+
76
+ const data = await response.json();
77
+ return data.choices[0].message.content;
78
+ }
79
+
80
+ /**
81
+ * Call Anthropic API
82
+ */
83
+ async callAnthropic(name, prompt, apiKey) {
84
+ const model = this.config.model || 'claude-3-sonnet-20240229';
85
+ const systemPrompt = this.getSystemPrompt(name);
86
+
87
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
88
+ method: 'POST',
89
+ headers: {
90
+ 'Content-Type': 'application/json',
91
+ 'x-api-key': apiKey,
92
+ 'anthropic-version': '2023-06-01'
93
+ },
94
+ body: JSON.stringify({
95
+ model: model,
96
+ max_tokens: 4000,
97
+ system: systemPrompt,
98
+ messages: [
99
+ { role: 'user', content: prompt }
100
+ ]
101
+ })
102
+ });
103
+
104
+ if (!response.ok) {
105
+ const errorData = await response.json();
106
+ throw new Error(`Anthropic API error: ${errorData.error?.message || response.statusText}`);
107
+ }
108
+
109
+ const data = await response.json();
110
+ return data.content[0].text;
111
+ }
112
+
113
+ /**
114
+ * Get system prompt for the AI
115
+ */
116
+ getSystemPrompt(name) {
117
+ return `You are an expert design system engineer specializing in the Atomix design system.
118
+ Your task is to generate a high-quality React component named "${name}" based on the user's prompt.
119
+
120
+ The component should follow these rules:
121
+ 1. Use React and TypeScript.
122
+ 2. Use Atomix utility classes (u-*) and component classes (c-*).
123
+ 3. Follow the Atomix component structure (Props interface, functional component, exports).
124
+ 4. Include JSDoc comments for all props.
125
+ 5. Ensure the component is accessible (aria labels, roles).
126
+ 6. Return only a JSON object with the following structure:
127
+ {
128
+ "component": "Full component code as a string",
129
+ "styles": "Any custom CSS/SCSS if needed (optional)",
130
+ "tests": "Unit test code using Vitest and React Testing Library",
131
+ "stories": "Storybook story file code",
132
+ "readme": "Usage documentation in Markdown"
133
+ }
134
+ Ensure the output is a valid JSON object. Do not include any other text or explanation.`;
135
+ }
136
+
137
+ /**
138
+ * Parse AI response to extract files
139
+ */
140
+ parseAIResponse(content) {
141
+ try {
142
+ // Try to find JSON in the response if the AI included other text
143
+ const jsonMatch = content.match(/\{[\s\S]*\}/);
144
+ if (jsonMatch) {
145
+ return JSON.parse(jsonMatch[0]);
146
+ }
147
+ return JSON.parse(content);
148
+ } catch (error) {
149
+ logger.error('Failed to parse AI response as JSON. Raw content:');
150
+ console.log(content);
151
+ throw new Error('AI returned invalid JSON format. See console for raw output.');
152
+ }
153
+ }
154
+ }
155
+
156
+ export const aiEngine = new AIEngine();