@aiready/components 0.11.19 → 0.12.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.
- package/dist/components/button.d.ts +1 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +154 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/icons.tsx +155 -0
- package/src/utils/__tests__/formatters.test.ts +51 -0
- package/src/utils/__tests__/score.test.ts +40 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Unified shared components library (UI, charts, hooks, utilities) for AIReady",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"framer-motion": "^12.35.0",
|
|
66
66
|
"lucide-react": "^0.577.0",
|
|
67
67
|
"tailwind-merge": "^3.0.0",
|
|
68
|
-
"@aiready/core": "0.
|
|
68
|
+
"@aiready/core": "0.22.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@testing-library/jest-dom": "^6.6.5",
|
package/src/components/icons.tsx
CHANGED
|
@@ -390,6 +390,154 @@ export function RefreshCwIcon({
|
|
|
390
390
|
);
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
+
export function WalletIcon({
|
|
394
|
+
className = 'w-6 h-6',
|
|
395
|
+
...props
|
|
396
|
+
}: { className?: string } & React.SVGProps<SVGSVGElement>) {
|
|
397
|
+
return (
|
|
398
|
+
<svg
|
|
399
|
+
viewBox="0 0 24 24"
|
|
400
|
+
fill="none"
|
|
401
|
+
stroke="currentColor"
|
|
402
|
+
strokeWidth="2"
|
|
403
|
+
strokeLinecap="round"
|
|
404
|
+
strokeLinejoin="round"
|
|
405
|
+
className={className}
|
|
406
|
+
{...props}
|
|
407
|
+
>
|
|
408
|
+
<path d="M21 12V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-1" />
|
|
409
|
+
<path d="M16 12h5" />
|
|
410
|
+
<circle cx="16" cy="12" r="1" />
|
|
411
|
+
</svg>
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export function ClockIcon({
|
|
416
|
+
className = 'w-6 h-6',
|
|
417
|
+
...props
|
|
418
|
+
}: { className?: string } & React.SVGProps<SVGSVGElement>) {
|
|
419
|
+
return (
|
|
420
|
+
<svg
|
|
421
|
+
viewBox="0 0 24 24"
|
|
422
|
+
fill="none"
|
|
423
|
+
stroke="currentColor"
|
|
424
|
+
strokeWidth="2"
|
|
425
|
+
strokeLinecap="round"
|
|
426
|
+
strokeLinejoin="round"
|
|
427
|
+
className={className}
|
|
428
|
+
{...props}
|
|
429
|
+
>
|
|
430
|
+
<circle cx="12" cy="12" r="10" />
|
|
431
|
+
<polyline points="12 6 12 12 16 14" />
|
|
432
|
+
</svg>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export function ZapIcon({
|
|
437
|
+
className = 'w-6 h-6',
|
|
438
|
+
...props
|
|
439
|
+
}: { className?: string } & React.SVGProps<SVGSVGElement>) {
|
|
440
|
+
return (
|
|
441
|
+
<svg
|
|
442
|
+
viewBox="0 0 24 24"
|
|
443
|
+
fill="none"
|
|
444
|
+
stroke="currentColor"
|
|
445
|
+
strokeWidth="2"
|
|
446
|
+
strokeLinecap="round"
|
|
447
|
+
strokeLinejoin="round"
|
|
448
|
+
className={className}
|
|
449
|
+
{...props}
|
|
450
|
+
>
|
|
451
|
+
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
|
|
452
|
+
</svg>
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export function HammerIcon({
|
|
457
|
+
className = 'w-6 h-6',
|
|
458
|
+
...props
|
|
459
|
+
}: { className?: string } & React.SVGProps<SVGSVGElement>) {
|
|
460
|
+
return (
|
|
461
|
+
<svg
|
|
462
|
+
viewBox="0 0 24 24"
|
|
463
|
+
fill="none"
|
|
464
|
+
stroke="currentColor"
|
|
465
|
+
strokeWidth="2"
|
|
466
|
+
strokeLinecap="round"
|
|
467
|
+
strokeLinejoin="round"
|
|
468
|
+
className={className}
|
|
469
|
+
{...props}
|
|
470
|
+
>
|
|
471
|
+
<path d="M18.42 13.59L7.46 2.63a1 1 0 0 0-1.42 0l-4.7 4.7a1 1 0 0 0 0 1.42L11 18.23l1.07-1.07-1.41-1.41 1.42-1.42 1.41 1.41 1.41-1.41-1.41-1.41 1.42-1.42 1.41 1.41 2-2z" />
|
|
472
|
+
<path d="M13 18l6 6" />
|
|
473
|
+
</svg>
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export function ArrowRightIcon({
|
|
478
|
+
className = 'w-6 h-6',
|
|
479
|
+
...props
|
|
480
|
+
}: { className?: string } & React.SVGProps<SVGSVGElement>) {
|
|
481
|
+
return (
|
|
482
|
+
<svg
|
|
483
|
+
viewBox="0 0 24 24"
|
|
484
|
+
fill="none"
|
|
485
|
+
stroke="currentColor"
|
|
486
|
+
strokeWidth="2"
|
|
487
|
+
strokeLinecap="round"
|
|
488
|
+
strokeLinejoin="round"
|
|
489
|
+
className={className}
|
|
490
|
+
{...props}
|
|
491
|
+
>
|
|
492
|
+
<line x1="5" y1="12" x2="19" y2="12" />
|
|
493
|
+
<polyline points="12 5 19 12 12 19" />
|
|
494
|
+
</svg>
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export function ShieldCheckIcon({
|
|
499
|
+
className = 'w-6 h-6',
|
|
500
|
+
...props
|
|
501
|
+
}: { className?: string } & React.SVGProps<SVGSVGElement>) {
|
|
502
|
+
return (
|
|
503
|
+
<svg
|
|
504
|
+
viewBox="0 0 24 24"
|
|
505
|
+
fill="none"
|
|
506
|
+
stroke="currentColor"
|
|
507
|
+
strokeWidth="2"
|
|
508
|
+
strokeLinecap="round"
|
|
509
|
+
strokeLinejoin="round"
|
|
510
|
+
className={className}
|
|
511
|
+
{...props}
|
|
512
|
+
>
|
|
513
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
514
|
+
<path d="M9 12l2 2 4-4" />
|
|
515
|
+
</svg>
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export function AlertTriangleIcon({
|
|
520
|
+
className = 'w-6 h-6',
|
|
521
|
+
...props
|
|
522
|
+
}: { className?: string } & React.SVGProps<SVGSVGElement>) {
|
|
523
|
+
return (
|
|
524
|
+
<svg
|
|
525
|
+
viewBox="0 0 24 24"
|
|
526
|
+
fill="none"
|
|
527
|
+
stroke="currentColor"
|
|
528
|
+
strokeWidth="2"
|
|
529
|
+
strokeLinecap="round"
|
|
530
|
+
strokeLinejoin="round"
|
|
531
|
+
className={className}
|
|
532
|
+
{...props}
|
|
533
|
+
>
|
|
534
|
+
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
|
|
535
|
+
<line x1="12" y1="9" x2="12" y2="13" />
|
|
536
|
+
<line x1="12" y1="17" x2="12.01" y2="17" />
|
|
537
|
+
</svg>
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
393
541
|
export default {
|
|
394
542
|
RocketIcon,
|
|
395
543
|
ChartIcon,
|
|
@@ -406,4 +554,11 @@ export default {
|
|
|
406
554
|
BrainIcon,
|
|
407
555
|
TerminalIcon,
|
|
408
556
|
CommandLineIcon,
|
|
557
|
+
WalletIcon,
|
|
558
|
+
ClockIcon,
|
|
559
|
+
ZapIcon,
|
|
560
|
+
HammerIcon,
|
|
561
|
+
ArrowRightIcon,
|
|
562
|
+
ShieldCheckIcon,
|
|
563
|
+
AlertTriangleIcon,
|
|
409
564
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
formatNumber,
|
|
4
|
+
formatCompactNumber,
|
|
5
|
+
formatPercentage,
|
|
6
|
+
formatFileSize,
|
|
7
|
+
formatRelativeTime,
|
|
8
|
+
formatDuration,
|
|
9
|
+
formatMetric,
|
|
10
|
+
} from '../formatters';
|
|
11
|
+
|
|
12
|
+
describe('Formatters', () => {
|
|
13
|
+
it('should format numbers with commas', () => {
|
|
14
|
+
expect(formatNumber(1234567)).toBe('1,234,567');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should format compact numbers', () => {
|
|
18
|
+
expect(formatCompactNumber(1234)).toBe('1.2K');
|
|
19
|
+
expect(formatCompactNumber(1234567)).toBe('1.2M');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should format percentages', () => {
|
|
23
|
+
expect(formatPercentage(0.1234)).toBe('12.3%');
|
|
24
|
+
expect(formatPercentage(0.1234, 0)).toBe('12%');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should format file sizes', () => {
|
|
28
|
+
expect(formatFileSize(1024)).toBe('1.0 KB');
|
|
29
|
+
expect(formatFileSize(1048576)).toBe('1.0 MB');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should format relative time', () => {
|
|
33
|
+
const now = new Date();
|
|
34
|
+
const oneHourAgo = new Date(now.getTime() - 3600000);
|
|
35
|
+
expect(formatRelativeTime(oneHourAgo)).toBe('1 hour ago');
|
|
36
|
+
expect(formatRelativeTime(now)).toBe('just now');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should format duration', () => {
|
|
40
|
+
expect(formatDuration(3661000)).toBe('1h 1m 1s');
|
|
41
|
+
expect(formatDuration(61000)).toBe('1m 1s');
|
|
42
|
+
expect(formatDuration(1000)).toBe('1s');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should format metrics based on unit', () => {
|
|
46
|
+
expect(formatMetric(1024, 'bytes')).toBe('1.0 KB');
|
|
47
|
+
expect(formatMetric(0.5, 'percentage')).toBe('50.0%');
|
|
48
|
+
expect(formatMetric(3600000, 'duration')).toBe('1h 0m 0s');
|
|
49
|
+
expect(formatMetric(1200, 'number')).toBe('1.2K');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
scoreColor,
|
|
4
|
+
scoreBg,
|
|
5
|
+
scoreLabel,
|
|
6
|
+
scoreGlow,
|
|
7
|
+
getScoreRating,
|
|
8
|
+
} from '../score';
|
|
9
|
+
|
|
10
|
+
describe('Score Utilities', () => {
|
|
11
|
+
it('should return correct color for scores', () => {
|
|
12
|
+
expect(scoreColor(80)).toBe('text-emerald-400');
|
|
13
|
+
expect(scoreColor(60)).toBe('text-amber-400');
|
|
14
|
+
expect(scoreColor(30)).toBe('text-red-400');
|
|
15
|
+
expect(scoreColor(null)).toBe('text-slate-400');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should return correct background for scores', () => {
|
|
19
|
+
expect(scoreBg(80)).toContain('emerald');
|
|
20
|
+
expect(scoreBg(60)).toContain('amber');
|
|
21
|
+
expect(scoreBg(30)).toContain('red');
|
|
22
|
+
expect(scoreBg(null)).toContain('slate');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return correct labels', () => {
|
|
26
|
+
expect(scoreLabel(80)).toBe('AI-Ready');
|
|
27
|
+
expect(scoreLabel(60)).toBe('Needs Improvement');
|
|
28
|
+
expect(scoreLabel(30)).toBe('Critical Issues');
|
|
29
|
+
expect(scoreLabel(null)).toBe('Not analyzed');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should return correct rating strings', () => {
|
|
33
|
+
expect(getScoreRating(95)).toBe('excellent');
|
|
34
|
+
expect(getScoreRating(80)).toBe('good');
|
|
35
|
+
expect(getScoreRating(65)).toBe('fair');
|
|
36
|
+
expect(getScoreRating(45)).toBe('needs-work');
|
|
37
|
+
expect(getScoreRating(20)).toBe('critical');
|
|
38
|
+
expect(getScoreRating(null)).toBe('critical');
|
|
39
|
+
});
|
|
40
|
+
});
|