kyd-shared-badge 0.3.17 → 0.3.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kyd-shared-badge",
3
- "version": "0.3.17",
3
+ "version": "0.3.19",
4
4
  "private": false,
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
package/src/colors.ts CHANGED
@@ -64,4 +64,37 @@ const red3 = '#F5B7B3'
64
64
  const red4 = '#FADBDA'
65
65
  const red5 = '#FDF0EF'
66
66
 
67
- export { red1, red2, red3, red4, red5 }
67
+ export { red1, red2, red3, red4, red5 }
68
+
69
+
70
+
71
+ export function clampPercent(value?: number): number {
72
+ const n = Math.round(Number(value ?? 0))
73
+ if (Number.isNaN(n)) return 0
74
+ return Math.max(0, Math.min(100, n))
75
+ }
76
+
77
+ export function scoreToColorHex(score: number): string {
78
+ const pct = clampPercent(score)
79
+ if (pct <= 33) return red
80
+ if (pct <= 66) return yellow
81
+ return green
82
+ }
83
+
84
+ export function scoreToCssVar(score: number): string {
85
+ const pct = clampPercent(score)
86
+ if (pct <= 33) return `var(--status-negative, ${red})`
87
+ if (pct <= 66) return `var(--status-neutral, ${yellow})`
88
+ return `var(--status-positive, ${green})`
89
+ }
90
+
91
+ export function hexToRgba(hex: string, alpha: number): string {
92
+ const clean = hex.replace('#', '')
93
+ const r = parseInt(clean.substring(0, 2), 16)
94
+ const g = parseInt(clean.substring(2, 4), 16)
95
+ const b = parseInt(clean.substring(4, 6), 16)
96
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`
97
+ }
98
+
99
+
100
+
@@ -3,23 +3,11 @@
3
3
  import React from 'react';
4
4
  import BusinessRuleLink from './BusinessRuleLink';
5
5
  import { FiInfo } from 'react-icons/fi';
6
- import { green, yellow, red } from '../colors';
6
+ import { hexToRgba, scoreToColorHex, scoreToCssVar, clampPercent } from '../colors';
7
7
 
8
8
  type TopMover = { label?: string; uid?: string };
9
9
 
10
- const hexToRgba = (hex: string, alpha: number) => {
11
- const clean = hex.replace('#', '');
12
- const r = parseInt(clean.substring(0, 2), 16);
13
- const g = parseInt(clean.substring(2, 4), 16);
14
- const b = parseInt(clean.substring(4, 6), 16);
15
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
16
- };
17
-
18
- const pickTint = (score: number) => {
19
- if (score >= 75) return green;
20
- if (score >= 50) return yellow;
21
- return red;
22
- };
10
+ // color helpers moved to ../utils/color
23
11
 
24
12
  export default function GaugeCard({
25
13
  title,
@@ -38,7 +26,7 @@ export default function GaugeCard({
38
26
  topMoversTitle?: string;
39
27
  tooltipText?: string;
40
28
  }) {
41
- const pct = Math.max(0, Math.min(100, Math.round(Number(percent ?? 0))));
29
+ const pct = clampPercent(percent);
42
30
  const displayLabel = label || '';
43
31
  // Use a fixed internal coordinate system and scale the SVG to container for responsiveness
44
32
  const size = 280;
@@ -47,13 +35,8 @@ export default function GaugeCard({
47
35
  const circumference = Math.PI * radius;
48
36
  const progress = pct / 100;
49
37
  const dash = circumference * progress;
50
- const progressColor =
51
- pct <= 33
52
- ? `var(--status-negative, ${red})`
53
- : pct <= 66
54
- ? `var(--status-neutral, ${yellow})`
55
- : `var(--status-positive, ${green})`;
56
- const headerTint = hexToRgba(pickTint(pct), 0.06);
38
+ const progressColor = scoreToCssVar(pct);
39
+ const headerTint = hexToRgba(scoreToColorHex(pct), 0.06);
57
40
 
58
41
  return (
59
42
  <div
@@ -45,6 +45,8 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, badgeImage
45
45
  // Use the dynamic image if available, otherwise fall back to the score-based one.
46
46
  const finalBadgeImageUrl = badgeImageUrl || getBadgeImageUrl(score || 0);
47
47
  const tint = hexToRgba(pickTint(score || 0), 0.06);
48
+ const matchScore = typeof enterpriseMatch?.score === 'number' ? enterpriseMatch.score : undefined;
49
+ const matchTint = matchScore !== undefined ? hexToRgba(pickTint(matchScore), 0.06) : undefined;
48
50
 
49
51
  const formattedDate = updatedAt ? formatLocalDate(updatedAt, {
50
52
  year: 'numeric',
@@ -114,7 +116,7 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, badgeImage
114
116
  </span>
115
117
  </div>
116
118
  {typeof enterpriseMatch?.score === 'number' && (
117
- <span className="px-2 py-1 rounded text-xs font-semibold" style={{ background: 'var(--content-card-background)', border: '1px solid var(--icon-button-secondary)', color: 'var(--text-main)' }}>
119
+ <span className="px-2 py-1 rounded text-xs font-semibold" style={{ backgroundColor: 'var(--content-card-background)', backgroundImage: matchTint ? `linear-gradient(${matchTint}, ${matchTint})` : undefined, border: '1px solid var(--icon-button-secondary)', color: 'var(--text-main)' }}>
118
120
  {Math.round(enterpriseMatch.score)}%
119
121
  </span>
120
122
  )}
@@ -3,7 +3,7 @@
3
3
  import React from 'react';
4
4
  import BusinessRuleLink from './BusinessRuleLink';
5
5
  import { FiInfo } from 'react-icons/fi';
6
- import { green, yellow, red } from '../colors';
6
+ import { clampPercent, hexToRgba, scoreToColorHex } from '../colors';
7
7
 
8
8
  type TopMover = { label?: string; uid?: string };
9
9
 
@@ -24,32 +24,15 @@ export default function RiskCard({
24
24
  topMoversTitle?: string;
25
25
  tooltipText?: string;
26
26
  }) {
27
- const pctGood = Math.max(0, Math.min(100, Math.round(Number(percentGood ?? 0))));
27
+ const pctGood = clampPercent(percentGood);
28
28
  const displayLabel = label || '';
29
29
 
30
- const hexToRgba = (hex: string, alpha: number) => {
31
- const clean = hex.replace('#', '');
32
- const r = parseInt(clean.substring(0, 2), 16);
33
- const g = parseInt(clean.substring(2, 4), 16);
34
- const b = parseInt(clean.substring(4, 6), 16);
35
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
36
- };
30
+ // Background tint uses same thresholds as GaugeCard via scoreToColorHex
37
31
 
38
- const pickTint = (score: number) => {
39
- if (score >= 75) return green;
40
- if (score >= 50) return yellow;
41
- return red;
42
- };
32
+ // Foreground bar color uses same thresholds as GaugeCard based on overall score
33
+ const activeColor = scoreToColorHex(pctGood);
43
34
 
44
- // color bands by bar position (tallest -> lowest)
45
- // indices 4 and 3 (highest bars) => red, index 2 => yellow, indices 1 and 0 => green
46
- const colorForIndex = (index: number) => {
47
- if (index >= 3) return red;
48
- if (index === 2) return yellow;
49
- return green;
50
- };
51
-
52
- const headerTint = hexToRgba(pickTint(pctGood), 0.06);
35
+ const headerTint = hexToRgba(scoreToColorHex(pctGood), 0.06);
53
36
 
54
37
  // bar heights ascending representation
55
38
  const bars = [40, 60, 85, 110, 140];
@@ -101,7 +84,7 @@ export default function RiskCard({
101
84
  style={{
102
85
  width: 36,
103
86
  height: h,
104
- backgroundColor: i === activeIndex ? colorForIndex(i) : 'var(--icon-button-secondary)',
87
+ backgroundColor: i === activeIndex ? activeColor : 'var(--icon-button-secondary)',
105
88
  borderRadius: 4,
106
89
  }}
107
90
  />