@shohojdhara/atomix 0.5.0 → 0.5.1
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.
- package/dist/atomix.css +95 -69
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +1 -0
- package/dist/charts.js +231 -332
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -0
- package/dist/core.js +232 -333
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +1 -0
- package/dist/forms.js +231 -332
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +11 -2
- package/dist/heavy.js +233 -334
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.esm.js +228 -327
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +227 -326
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +11 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +188 -128
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +62 -90
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +153 -201
- package/src/components/AtomixGlass/glass-utils.ts +50 -0
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +52 -46
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +573 -236
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +88 -41
- package/src/components/AtomixGlass/stories/argTypes.ts +19 -19
- package/src/components/AtomixGlass/stories/shared-components.tsx +7 -12
- package/src/components/AtomixGlass/stories/types.ts +3 -3
- package/src/lib/composables/useAtomixGlass.ts +108 -71
- package/src/lib/composables/useAtomixGlassStyles.ts +0 -2
- package/src/lib/constants/components.ts +1 -0
- package/src/lib/types/components.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/06-components/_components.atomix-glass.scss +158 -97
- package/scripts/cli/__tests__/README.md +0 -81
- package/scripts/cli/__tests__/basic.test.js +0 -116
- package/scripts/cli/__tests__/clean.test.js +0 -278
- package/scripts/cli/__tests__/component-generator.test.js +0 -332
- package/scripts/cli/__tests__/component-validator.test.js +0 -433
- package/scripts/cli/__tests__/generator.test.js +0 -613
- package/scripts/cli/__tests__/glass-motion.test.js +0 -256
- package/scripts/cli/__tests__/integration.test.js +0 -938
- package/scripts/cli/__tests__/migrate.test.js +0 -74
- package/scripts/cli/__tests__/security.test.js +0 -206
- package/scripts/cli/__tests__/test-setup.js +0 -135
- package/scripts/cli/__tests__/theme-bridge.test.js +0 -507
- package/scripts/cli/__tests__/token-manager.test.js +0 -251
- package/scripts/cli/__tests__/token-provider.test.js +0 -361
- package/scripts/cli/__tests__/utils.test.js +0 -165
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -216
- package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +0 -95
- package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +0 -212
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +0 -131
- package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +0 -348
- package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +0 -410
- package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +0 -436
- package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +0 -264
- package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +0 -247
- package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +0 -418
- package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +0 -402
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +0 -1082
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +0 -497
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +0 -103
- package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +0 -335
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +0 -395
- package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +0 -441
- package/src/components/TypedButton/TypedButton.stories.tsx +0 -59
- package/src/components/TypedButton/TypedButton.tsx +0 -39
- package/src/components/TypedButton/index.ts +0 -2
- package/src/lib/composables/useTypedButton.ts +0 -66
|
@@ -1,433 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component Validator Tests
|
|
3
|
-
* Tests for Phase 2: Design System Architecture Enforcement
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
7
|
-
import {
|
|
8
|
-
ComponentValidator,
|
|
9
|
-
COMPONENT_RULES,
|
|
10
|
-
COMPONENT_SEVERITY,
|
|
11
|
-
componentValidator
|
|
12
|
-
} from '../internal/component-validator.js';
|
|
13
|
-
|
|
14
|
-
describe('ComponentValidator', () => {
|
|
15
|
-
let validator;
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
validator = new ComponentValidator();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
describe('Initialization', () => {
|
|
22
|
-
it('should create a new ComponentValidator instance', () => {
|
|
23
|
-
expect(validator).toBeInstanceOf(ComponentValidator);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should register all built-in rules', () => {
|
|
27
|
-
expect(validator.rules.size).toBeGreaterThan(0);
|
|
28
|
-
expect(validator.rules.has('FORWARD_REF_REQUIRED')).toBe(true);
|
|
29
|
-
expect(validator.rules.has('DISPLAY_NAME_REQUIRED')).toBe(true);
|
|
30
|
-
expect(validator.rules.has('TYPESCRIPT_TYPES_REQUIRED')).toBe(true);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should have all rules enabled by default', () => {
|
|
34
|
-
expect(validator.enabledRules.length).toBeGreaterThan(0);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
describe('ForwardRef Validation', () => {
|
|
39
|
-
it('should detect missing forwardRef', () => {
|
|
40
|
-
const content = `
|
|
41
|
-
export const Button = (props) => {
|
|
42
|
-
return <div {...props} />;
|
|
43
|
-
};
|
|
44
|
-
`;
|
|
45
|
-
|
|
46
|
-
const result = validator.validate(content, 'Button');
|
|
47
|
-
|
|
48
|
-
const forwardRefIssue = result.issues.find(i => i.rule === 'forward-ref-required');
|
|
49
|
-
expect(forwardRefIssue).toBeDefined();
|
|
50
|
-
expect(forwardRefIssue.severity).toBe(COMPONENT_SEVERITY.ERROR);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should pass when forwardRef is used', () => {
|
|
54
|
-
const content = `
|
|
55
|
-
import React, { forwardRef } from 'react';
|
|
56
|
-
|
|
57
|
-
export const Button = forwardRef<HTMLDivElement, ButtonProps>(
|
|
58
|
-
(props, ref) => {
|
|
59
|
-
return <div ref={ref} {...props} />;
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
`;
|
|
63
|
-
|
|
64
|
-
const result = validator.validate(content, 'Button');
|
|
65
|
-
|
|
66
|
-
const forwardRefIssue = result.issues.find(i => i.rule === 'forward-ref-required');
|
|
67
|
-
expect(forwardRefIssue).toBeUndefined();
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('DisplayName Validation', () => {
|
|
72
|
-
it('should detect missing displayName', () => {
|
|
73
|
-
const content = `
|
|
74
|
-
export const Button = forwardRef((props, ref) => {
|
|
75
|
-
return <div ref={ref} {...props} />;
|
|
76
|
-
});
|
|
77
|
-
`;
|
|
78
|
-
|
|
79
|
-
const result = validator.validate(content, 'Button');
|
|
80
|
-
|
|
81
|
-
const displayNameIssue = result.issues.find(i => i.rule === 'display-name-required');
|
|
82
|
-
expect(displayNameIssue).toBeDefined();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should pass when displayName is correctly assigned', () => {
|
|
86
|
-
const content = `
|
|
87
|
-
export const Button = forwardRef((props, ref) => {
|
|
88
|
-
return <div ref={ref} {...props} />;
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
Button.displayName = 'Button';
|
|
92
|
-
`;
|
|
93
|
-
|
|
94
|
-
const result = validator.validate(content, 'Button');
|
|
95
|
-
|
|
96
|
-
const displayNameIssue = result.issues.find(i => i.rule === 'display-name-required');
|
|
97
|
-
expect(displayNameIssue).toBeUndefined();
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
describe('JSDoc Validation', () => {
|
|
102
|
-
it('should detect missing JSDoc', () => {
|
|
103
|
-
const content = `
|
|
104
|
-
export const Button = forwardRef((props, ref) => {
|
|
105
|
-
return <div ref={ref} {...props} />;
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
Button.displayName = 'Button';
|
|
109
|
-
`;
|
|
110
|
-
|
|
111
|
-
const result = validator.validate(content, 'Button');
|
|
112
|
-
|
|
113
|
-
const jsdocIssue = result.issues.find(i => i.rule === 'jsdoc-required');
|
|
114
|
-
expect(jsdocIssue).toBeDefined();
|
|
115
|
-
expect(jsdocIssue.severity).toBe(COMPONENT_SEVERITY.WARNING);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should pass when JSDoc is present', () => {
|
|
119
|
-
const content = `
|
|
120
|
-
/**
|
|
121
|
-
* Button Component
|
|
122
|
-
* @param {ButtonProps} props - Component properties
|
|
123
|
-
* @returns {JSX.Element} The rendered button
|
|
124
|
-
*/
|
|
125
|
-
export const Button = forwardRef((props, ref) => {
|
|
126
|
-
return <div ref={ref} {...props} />;
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
Button.displayName = 'Button';
|
|
130
|
-
`;
|
|
131
|
-
|
|
132
|
-
const result = validator.validate(content, 'Button');
|
|
133
|
-
|
|
134
|
-
const jsdocIssue = result.issues.find(i => i.rule === 'jsdoc-required');
|
|
135
|
-
expect(jsdocIssue).toBeUndefined();
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe('TypeScript Types Validation', () => {
|
|
140
|
-
it('should detect missing Props type', () => {
|
|
141
|
-
const content = `
|
|
142
|
-
export const Button = forwardRef((props, ref) => {
|
|
143
|
-
return <div ref={ref} {...props} />;
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
Button.displayName = 'Button';
|
|
147
|
-
`;
|
|
148
|
-
|
|
149
|
-
const result = validator.validate(content, 'Button');
|
|
150
|
-
|
|
151
|
-
const typesIssue = result.issues.find(i => i.rule === 'typescript-types-required');
|
|
152
|
-
expect(typesIssue).toBeDefined();
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should pass with local Props interface', () => {
|
|
156
|
-
const content = `
|
|
157
|
-
interface ButtonProps {
|
|
158
|
-
variant?: string;
|
|
159
|
-
size?: string;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export const Button = forwardRef<HTMLDivElement, ButtonProps>(
|
|
163
|
-
(props, ref) => {
|
|
164
|
-
return <div ref={ref} {...props} />;
|
|
165
|
-
}
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
Button.displayName = 'Button';
|
|
169
|
-
`;
|
|
170
|
-
|
|
171
|
-
const result = validator.validate(content, 'Button');
|
|
172
|
-
|
|
173
|
-
const typesIssue = result.issues.find(i => i.rule === 'typescript-types-required');
|
|
174
|
-
expect(typesIssue).toBeUndefined();
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('should pass with imported Props type', () => {
|
|
178
|
-
const content = `
|
|
179
|
-
import type { ButtonProps } from '../../types/components';
|
|
180
|
-
|
|
181
|
-
export const Button = forwardRef<HTMLDivElement, ButtonProps>(
|
|
182
|
-
(props, ref) => {
|
|
183
|
-
return <div ref={ref} {...props} />;
|
|
184
|
-
}
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
Button.displayName = 'Button';
|
|
188
|
-
`;
|
|
189
|
-
|
|
190
|
-
const result = validator.validate(content, 'Button');
|
|
191
|
-
|
|
192
|
-
const typesIssue = result.issues.find(i => i.rule === 'typescript-types-required');
|
|
193
|
-
expect(typesIssue).toBeUndefined();
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
describe('Accessibility Validation', () => {
|
|
198
|
-
it('should detect missing accessibility attributes', () => {
|
|
199
|
-
const content = `
|
|
200
|
-
export const Button = forwardRef((props, ref) => {
|
|
201
|
-
return <div ref={ref} {...props} />;
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
Button.displayName = 'Button';
|
|
205
|
-
`;
|
|
206
|
-
|
|
207
|
-
const result = validator.validate(content, 'Button');
|
|
208
|
-
|
|
209
|
-
const a11yIssue = result.issues.find(i => i.rule === 'accessibility-attributes');
|
|
210
|
-
expect(a11yIssue).toBeDefined();
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it('should pass with aria-label', () => {
|
|
214
|
-
const content = `
|
|
215
|
-
export const Button = forwardRef((props, ref) => {
|
|
216
|
-
return <div ref={ref} aria-label="Click me" {...props} />;
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
Button.displayName = 'Button';
|
|
220
|
-
`;
|
|
221
|
-
|
|
222
|
-
const result = validator.validate(content, 'Button');
|
|
223
|
-
|
|
224
|
-
const a11yIssue = result.issues.find(i => i.rule === 'accessibility-attributes');
|
|
225
|
-
expect(a11yIssue).toBeUndefined();
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
describe('Hardcoded Colors Validation', () => {
|
|
230
|
-
it('should detect hardcoded hex colors', () => {
|
|
231
|
-
const content = `
|
|
232
|
-
export const Button = forwardRef((props, ref) => {
|
|
233
|
-
return <div ref={ref} style={{ color: '#ff0000' }} {...props} />;
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
Button.displayName = 'Button';
|
|
237
|
-
`;
|
|
238
|
-
|
|
239
|
-
const result = validator.validate(content, 'Button');
|
|
240
|
-
|
|
241
|
-
const colorIssue = result.issues.find(i => i.rule === 'no-hardcoded-colors');
|
|
242
|
-
expect(colorIssue).toBeDefined();
|
|
243
|
-
expect(colorIssue.matches).toContain('#ff0000');
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('should detect hardcoded RGB colors', () => {
|
|
247
|
-
const content = `
|
|
248
|
-
export const Button = forwardRef((props, ref) => {
|
|
249
|
-
return <div ref={ref} style={{ backgroundColor: 'rgb(255, 0, 0)' }} {...props} />;
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
Button.displayName = 'Button';
|
|
253
|
-
`;
|
|
254
|
-
|
|
255
|
-
const result = validator.validate(content, 'Button');
|
|
256
|
-
|
|
257
|
-
const colorIssue = result.issues.find(i => i.rule === 'no-hardcoded-colors');
|
|
258
|
-
expect(colorIssue).toBeDefined();
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it('should pass without hardcoded colors', () => {
|
|
262
|
-
const content = `
|
|
263
|
-
export const Button = forwardRef((props, ref) => {
|
|
264
|
-
return <div ref={ref} style={{ color: 'var(--color-primary)' }} {...props} />;
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
Button.displayName = 'Button';
|
|
268
|
-
`;
|
|
269
|
-
|
|
270
|
-
const result = validator.validate(content, 'Button');
|
|
271
|
-
|
|
272
|
-
const colorIssue = result.issues.find(i => i.rule === 'no-hardcoded-colors');
|
|
273
|
-
expect(colorIssue).toBeUndefined();
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
describe('Memo Usage Validation', () => {
|
|
278
|
-
it('should suggest using memo', () => {
|
|
279
|
-
const content = `
|
|
280
|
-
export const Button = forwardRef((props, ref) => {
|
|
281
|
-
return <div ref={ref} {...props} />;
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
Button.displayName = 'Button';
|
|
285
|
-
`;
|
|
286
|
-
|
|
287
|
-
const result = validator.validate(content, 'Button');
|
|
288
|
-
|
|
289
|
-
const memoIssue = result.issues.find(i => i.rule === 'memo-usage');
|
|
290
|
-
expect(memoIssue).toBeDefined();
|
|
291
|
-
expect(memoIssue.severity).toBe(COMPONENT_SEVERITY.INFO);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('should pass when memo is used', () => {
|
|
295
|
-
const content = `
|
|
296
|
-
import React, { memo, forwardRef } from 'react';
|
|
297
|
-
|
|
298
|
-
export const Button = memo(
|
|
299
|
-
forwardRef((props, ref) => {
|
|
300
|
-
return <div ref={ref} {...props} />;
|
|
301
|
-
})
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
Button.displayName = 'Button';
|
|
305
|
-
`;
|
|
306
|
-
|
|
307
|
-
const result = validator.validate(content, 'Button');
|
|
308
|
-
|
|
309
|
-
const memoIssue = result.issues.find(i => i.rule === 'memo-usage');
|
|
310
|
-
expect(memoIssue).toBeUndefined();
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
describe('Rule Management', () => {
|
|
315
|
-
it('should toggle rules on/off', () => {
|
|
316
|
-
const initialCount = validator.enabledRules.length;
|
|
317
|
-
|
|
318
|
-
validator.toggleRule('FORWARD_REF_REQUIRED', false);
|
|
319
|
-
expect(validator.enabledRules).not.toContain('FORWARD_REF_REQUIRED');
|
|
320
|
-
|
|
321
|
-
validator.toggleRule('FORWARD_REF_REQUIRED', true);
|
|
322
|
-
expect(validator.enabledRules).toContain('FORWARD_REF_REQUIRED');
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
it('should allow registering custom rules', () => {
|
|
326
|
-
const customRule = {
|
|
327
|
-
name: 'custom-rule',
|
|
328
|
-
description: 'Custom validation rule',
|
|
329
|
-
severity: COMPONENT_SEVERITY.INFO,
|
|
330
|
-
validate: (content) => []
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
validator.registerRule('CUSTOM_RULE', customRule);
|
|
334
|
-
|
|
335
|
-
expect(validator.rules.has('CUSTOM_RULE')).toBe(true);
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
it('should reject invalid rules', () => {
|
|
339
|
-
expect(() => {
|
|
340
|
-
validator.registerRule('INVALID', { name: 'test' });
|
|
341
|
-
}).toThrow('must have name, validate, and severity');
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
describe('Validation Report', () => {
|
|
346
|
-
it('should generate formatted report', () => {
|
|
347
|
-
const content = `
|
|
348
|
-
export const Button = (props) => {
|
|
349
|
-
return <div style={{ color: '#ff0000' }} {...props} />;
|
|
350
|
-
};
|
|
351
|
-
`;
|
|
352
|
-
|
|
353
|
-
const result = validator.validate(content, 'Button');
|
|
354
|
-
const report = validator.getReport(result, 'Button');
|
|
355
|
-
|
|
356
|
-
expect(report).toContain('Component Validation Report: Button');
|
|
357
|
-
expect(report).toContain('Status:');
|
|
358
|
-
expect(report).toContain('Summary:');
|
|
359
|
-
expect(report).toContain('Errors:');
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it('should sort issues by severity', () => {
|
|
363
|
-
const content = `
|
|
364
|
-
export const Button = (props) => {
|
|
365
|
-
return <div style={{ color: '#ff0000' }} {...props} />;
|
|
366
|
-
};
|
|
367
|
-
`;
|
|
368
|
-
|
|
369
|
-
const result = validator.validate(content, 'Button');
|
|
370
|
-
const report = validator.getReport(result, 'Button');
|
|
371
|
-
|
|
372
|
-
// Errors should appear before warnings and info
|
|
373
|
-
const errorIndex = report.indexOf('❌');
|
|
374
|
-
const warningIndex = report.indexOf('⚠️');
|
|
375
|
-
const infoIndex = report.indexOf('ℹ️');
|
|
376
|
-
|
|
377
|
-
if (errorIndex !== -1 && warningIndex !== -1) {
|
|
378
|
-
expect(errorIndex).toBeLessThan(warningIndex);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
describe('Integration Tests', () => {
|
|
384
|
-
it('should validate complete component correctly', () => {
|
|
385
|
-
const content = `
|
|
386
|
-
import React, { memo, forwardRef } from 'react';
|
|
387
|
-
import type { ButtonProps } from '../../types/components';
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Button Component
|
|
391
|
-
* @param {ButtonProps} props - Component properties
|
|
392
|
-
* @returns {JSX.Element} Rendered button
|
|
393
|
-
*/
|
|
394
|
-
export const Button = memo(
|
|
395
|
-
forwardRef<HTMLDivElement, ButtonProps>(
|
|
396
|
-
({ children, variant = 'primary', 'aria-label': ariaLabel, ...props }, ref) => {
|
|
397
|
-
return (
|
|
398
|
-
<div
|
|
399
|
-
ref={ref}
|
|
400
|
-
className={\`c-button c-button--variant-\${variant}\`}
|
|
401
|
-
aria-label={ariaLabel}
|
|
402
|
-
{...props}
|
|
403
|
-
>
|
|
404
|
-
{children}
|
|
405
|
-
</div>
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
)
|
|
409
|
-
);
|
|
410
|
-
|
|
411
|
-
Button.displayName = 'Button';
|
|
412
|
-
`;
|
|
413
|
-
|
|
414
|
-
const result = validator.validate(content, 'Button');
|
|
415
|
-
|
|
416
|
-
// Should have no errors (warnings and info are OK)
|
|
417
|
-
expect(result.summary.errors).toBe(0);
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
it('should fail validation with multiple errors', () => {
|
|
421
|
-
const content = `
|
|
422
|
-
export const Button = (props) => {
|
|
423
|
-
return <div style={{ color: '#ff0000' }} {...props} />;
|
|
424
|
-
};
|
|
425
|
-
`;
|
|
426
|
-
|
|
427
|
-
const result = validator.validate(content, 'Button');
|
|
428
|
-
|
|
429
|
-
expect(result.valid).toBe(false);
|
|
430
|
-
expect(result.summary.errors).toBeGreaterThan(0);
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
});
|