uibee 2.15.0 → 2.16.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/bun.lock +680 -0
- package/dist/src/components/index.d.ts +2 -0
- package/dist/src/components/index.js +4 -0
- package/dist/src/components/layout/toggle.d.ts +14 -0
- package/dist/src/components/layout/toggle.js +12 -0
- package/dist/src/components/vulnerability/constants.d.ts +4 -0
- package/dist/src/components/vulnerability/constants.js +14 -0
- package/dist/src/components/vulnerability/severityPill.d.ts +8 -0
- package/dist/src/components/vulnerability/severityPill.js +8 -0
- package/dist/src/globals.css +110 -1
- package/package.json +12 -12
- package/src/components/index.ts +7 -1
- package/src/components/layout/toggle.tsx +62 -0
- package/src/components/vulnerability/constants.ts +17 -0
- package/src/components/vulnerability/severityPill.tsx +22 -0
- package/tsconfig.json +1 -0
|
@@ -26,3 +26,5 @@ export { default as Table } from './table/table';
|
|
|
26
26
|
export { default as Pagination } from './table/pagination';
|
|
27
27
|
export { default as MarkdownRender } from './markdownrender/markdownRender';
|
|
28
28
|
export { default as ConfirmPopup } from './confirm/confirmPopup';
|
|
29
|
+
export { default as SeverityPill } from './vulnerability/severityPill';
|
|
30
|
+
export { default as Toggle } from './layout/toggle';
|
|
@@ -38,3 +38,7 @@ export { default as Pagination } from './table/pagination';
|
|
|
38
38
|
export { default as MarkdownRender } from './markdownrender/markdownRender';
|
|
39
39
|
// Confirm
|
|
40
40
|
export { default as ConfirmPopup } from './confirm/confirmPopup';
|
|
41
|
+
// Vulnerability
|
|
42
|
+
export { default as SeverityPill } from './vulnerability/severityPill';
|
|
43
|
+
// Layout
|
|
44
|
+
export { default as Toggle } from './layout/toggle';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type ToggleOption<T> = {
|
|
2
|
+
value: T;
|
|
3
|
+
label?: string;
|
|
4
|
+
text?: string;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
type ToggleProps<T> = {
|
|
8
|
+
value: T;
|
|
9
|
+
onChange: (value: T) => void;
|
|
10
|
+
left: ToggleOption<T>;
|
|
11
|
+
right: ToggleOption<T>;
|
|
12
|
+
};
|
|
13
|
+
export default function Toggle<T>({ value, onChange, left, right, }: ToggleProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export default function Toggle({ value, onChange, left, right, }) {
|
|
3
|
+
const active = 'bg-login-200 text-login-950 shadow';
|
|
4
|
+
const idle = 'text-login-200 hover:bg-login-50/10 hover:text-login-50';
|
|
5
|
+
const base = 'flex items-center justify-center rounded-full transition gap-1';
|
|
6
|
+
function renderContent(opt) {
|
|
7
|
+
return (_jsxs(_Fragment, { children: [opt.icon, opt.text && _jsx("span", { children: opt.text })] }));
|
|
8
|
+
}
|
|
9
|
+
const isLeftActive = value === left.value;
|
|
10
|
+
const isRightActive = value === right.value;
|
|
11
|
+
return (_jsxs("div", { className: 'flex items-center rounded-full border border-login-100/10 bg-login-50/5 p-1', children: [_jsx("button", { type: 'button', onClick: () => onChange(left.value), "aria-label": left.label ?? left.text, "aria-pressed": isLeftActive, className: `${base} px-2 h-7 ${isLeftActive ? active : idle}`, children: renderContent(left) }), _jsx("button", { type: 'button', onClick: () => onChange(right.value), "aria-label": right.label ?? right.text, "aria-pressed": isRightActive, className: `${base} px-2 h-7 ${isRightActive ? active : idle}`, children: renderContent(right) })] }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const severityLabel = {
|
|
2
|
+
critical: 'Critical',
|
|
3
|
+
high: 'High',
|
|
4
|
+
medium: 'Medium',
|
|
5
|
+
low: 'Low',
|
|
6
|
+
unknown: 'Unknown',
|
|
7
|
+
};
|
|
8
|
+
export const severityClasses = {
|
|
9
|
+
critical: 'border-red-400/25 bg-red-500/10 text-red-200',
|
|
10
|
+
high: 'border-orange-400/25 bg-orange-500/10 text-orange-200',
|
|
11
|
+
medium: 'border-amber-400/25 bg-amber-500/10 text-amber-200',
|
|
12
|
+
low: 'border-sky-400/25 bg-sky-500/10 text-sky-200',
|
|
13
|
+
unknown: 'border-login-100/10 bg-login-50/5 text-login-200',
|
|
14
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type SeverityLevel = 'critical' | 'high' | 'medium' | 'low' | 'unknown';
|
|
2
|
+
type SeverityPillProps = {
|
|
3
|
+
severity: SeverityLevel;
|
|
4
|
+
count: number;
|
|
5
|
+
compact?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export default function SeverityPill({ severity, count, compact }: SeverityPillProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { severityClasses, severityLabel } from './constants';
|
|
3
|
+
export default function SeverityPill({ severity, count, compact = false }) {
|
|
4
|
+
if (count === 0) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
return (_jsxs("div", { className: `rounded-xl border ${compact ? 'px-3 py-2' : 'p-3'} ${severityClasses[severity]}`, children: [_jsx("div", { className: 'text-[11px] font-medium uppercase tracking-[0.18em]', children: severityLabel[severity] }), _jsx("div", { className: `${compact ? 'mt-1 text-sm' : 'mt-2 text-lg'} font-semibold`, children: count })] }));
|
|
8
|
+
}
|
package/dist/src/globals.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! tailwindcss v4.2.
|
|
1
|
+
/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */
|
|
2
2
|
@layer properties;
|
|
3
3
|
@layer theme, base, components, utilities;
|
|
4
4
|
@layer theme {
|
|
@@ -13,12 +13,21 @@
|
|
|
13
13
|
--color-red-600: oklch(57.7% 0.245 27.325);
|
|
14
14
|
--color-red-700: oklch(50.5% 0.213 27.518);
|
|
15
15
|
--color-red-900: oklch(39.6% 0.141 25.723);
|
|
16
|
+
--color-orange-200: oklch(90.1% 0.076 70.697);
|
|
17
|
+
--color-orange-400: oklch(75% 0.183 55.934);
|
|
18
|
+
--color-orange-500: oklch(70.5% 0.213 47.604);
|
|
19
|
+
--color-amber-200: oklch(92.4% 0.12 95.746);
|
|
20
|
+
--color-amber-400: oklch(82.8% 0.189 84.429);
|
|
21
|
+
--color-amber-500: oklch(76.9% 0.188 70.08);
|
|
16
22
|
--color-yellow-400: oklch(85.2% 0.199 91.936);
|
|
17
23
|
--color-yellow-500: oklch(79.5% 0.184 86.047);
|
|
18
24
|
--color-yellow-600: oklch(68.1% 0.162 75.834);
|
|
19
25
|
--color-green-400: oklch(79.2% 0.209 151.711);
|
|
20
26
|
--color-green-500: oklch(72.3% 0.219 149.579);
|
|
21
27
|
--color-green-600: oklch(62.7% 0.194 149.214);
|
|
28
|
+
--color-sky-200: oklch(90.1% 0.058 230.902);
|
|
29
|
+
--color-sky-400: oklch(74.6% 0.16 232.661);
|
|
30
|
+
--color-sky-500: oklch(68.5% 0.169 237.323);
|
|
22
31
|
--color-blue-400: oklch(70.7% 0.165 254.624);
|
|
23
32
|
--color-blue-500: oklch(62.3% 0.214 259.815);
|
|
24
33
|
--color-blue-600: oklch(54.6% 0.245 262.881);
|
|
@@ -71,6 +80,7 @@
|
|
|
71
80
|
--default-font-family: var(--font-sans);
|
|
72
81
|
--default-mono-font-family: var(--font-mono);
|
|
73
82
|
--color-login: #fd8738;
|
|
83
|
+
--color-login-950: #0e0e0e;
|
|
74
84
|
--color-login-900: #121212;
|
|
75
85
|
--color-login-800: #181818;
|
|
76
86
|
--color-login-700: #1a1a1a;
|
|
@@ -1119,6 +1129,9 @@
|
|
|
1119
1129
|
.h-6 {
|
|
1120
1130
|
height: calc(var(--spacing) * 6);
|
|
1121
1131
|
}
|
|
1132
|
+
.h-7 {
|
|
1133
|
+
height: calc(var(--spacing) * 7);
|
|
1134
|
+
}
|
|
1122
1135
|
.h-8 {
|
|
1123
1136
|
height: calc(var(--spacing) * 8);
|
|
1124
1137
|
}
|
|
@@ -1509,12 +1522,24 @@
|
|
|
1509
1522
|
--tw-border-style: none;
|
|
1510
1523
|
border-style: none;
|
|
1511
1524
|
}
|
|
1525
|
+
.border-amber-400\/25 {
|
|
1526
|
+
border-color: color-mix(in srgb, oklch(82.8% 0.189 84.429) 25%, transparent);
|
|
1527
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1528
|
+
border-color: color-mix(in oklab, var(--color-amber-400) 25%, transparent);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1512
1531
|
.border-gray-200 {
|
|
1513
1532
|
border-color: var(--color-gray-200);
|
|
1514
1533
|
}
|
|
1515
1534
|
.border-login-50 {
|
|
1516
1535
|
border-color: var(--color-login-50);
|
|
1517
1536
|
}
|
|
1537
|
+
.border-login-100\/10 {
|
|
1538
|
+
border-color: color-mix(in srgb, #b0b0b0 10%, transparent);
|
|
1539
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1540
|
+
border-color: color-mix(in oklab, var(--color-login-100) 10%, transparent);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1518
1543
|
.border-login-200 {
|
|
1519
1544
|
border-color: var(--color-login-200);
|
|
1520
1545
|
}
|
|
@@ -1539,9 +1564,27 @@
|
|
|
1539
1564
|
border-color: color-mix(in oklab, var(--color-login-600) 50%, transparent);
|
|
1540
1565
|
}
|
|
1541
1566
|
}
|
|
1567
|
+
.border-orange-400\/25 {
|
|
1568
|
+
border-color: color-mix(in srgb, oklch(75% 0.183 55.934) 25%, transparent);
|
|
1569
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1570
|
+
border-color: color-mix(in oklab, var(--color-orange-400) 25%, transparent);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
.border-red-400\/25 {
|
|
1574
|
+
border-color: color-mix(in srgb, oklch(70.4% 0.191 22.216) 25%, transparent);
|
|
1575
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1576
|
+
border-color: color-mix(in oklab, var(--color-red-400) 25%, transparent);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1542
1579
|
.border-red-500 {
|
|
1543
1580
|
border-color: var(--color-red-500);
|
|
1544
1581
|
}
|
|
1582
|
+
.border-sky-400\/25 {
|
|
1583
|
+
border-color: color-mix(in srgb, oklch(74.6% 0.16 232.661) 25%, transparent);
|
|
1584
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1585
|
+
border-color: color-mix(in oklab, var(--color-sky-400) 25%, transparent);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1545
1588
|
.border-white {
|
|
1546
1589
|
border-color: var(--color-white);
|
|
1547
1590
|
}
|
|
@@ -1551,6 +1594,12 @@
|
|
|
1551
1594
|
.bg-\[\#18181899\] {
|
|
1552
1595
|
background-color: #18181899;
|
|
1553
1596
|
}
|
|
1597
|
+
.bg-amber-500\/10 {
|
|
1598
|
+
background-color: color-mix(in srgb, oklch(76.9% 0.188 70.08) 10%, transparent);
|
|
1599
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1600
|
+
background-color: color-mix(in oklab, var(--color-amber-500) 10%, transparent);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1554
1603
|
.bg-black\/60 {
|
|
1555
1604
|
background-color: color-mix(in srgb, #000 60%, transparent);
|
|
1556
1605
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -1614,6 +1663,9 @@
|
|
|
1614
1663
|
background-color: color-mix(in oklab, var(--color-login-50) 5%, transparent);
|
|
1615
1664
|
}
|
|
1616
1665
|
}
|
|
1666
|
+
.bg-login-200 {
|
|
1667
|
+
background-color: var(--color-login-200);
|
|
1668
|
+
}
|
|
1617
1669
|
.bg-login-400 {
|
|
1618
1670
|
background-color: var(--color-login-400);
|
|
1619
1671
|
}
|
|
@@ -1668,6 +1720,18 @@
|
|
|
1668
1720
|
background-color: color-mix(in oklab, var(--color-login) 70%, transparent);
|
|
1669
1721
|
}
|
|
1670
1722
|
}
|
|
1723
|
+
.bg-orange-500\/10 {
|
|
1724
|
+
background-color: color-mix(in srgb, oklch(70.5% 0.213 47.604) 10%, transparent);
|
|
1725
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1726
|
+
background-color: color-mix(in oklab, var(--color-orange-500) 10%, transparent);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
.bg-red-500\/10 {
|
|
1730
|
+
background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 10%, transparent);
|
|
1731
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1732
|
+
background-color: color-mix(in oklab, var(--color-red-500) 10%, transparent);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1671
1735
|
.bg-red-500\/20 {
|
|
1672
1736
|
background-color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 20%, transparent);
|
|
1673
1737
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -1689,6 +1753,12 @@
|
|
|
1689
1753
|
.bg-red-900 {
|
|
1690
1754
|
background-color: var(--color-red-900);
|
|
1691
1755
|
}
|
|
1756
|
+
.bg-sky-500\/10 {
|
|
1757
|
+
background-color: color-mix(in srgb, oklch(68.5% 0.169 237.323) 10%, transparent);
|
|
1758
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1759
|
+
background-color: color-mix(in oklab, var(--color-sky-500) 10%, transparent);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1692
1762
|
.bg-transparent {
|
|
1693
1763
|
background-color: transparent;
|
|
1694
1764
|
}
|
|
@@ -1931,6 +2001,9 @@
|
|
|
1931
2001
|
font-size: var(--text-xs);
|
|
1932
2002
|
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
1933
2003
|
}
|
|
2004
|
+
.text-\[11px\] {
|
|
2005
|
+
font-size: 11px;
|
|
2006
|
+
}
|
|
1934
2007
|
.leading-4 {
|
|
1935
2008
|
--tw-leading: calc(var(--spacing) * 4);
|
|
1936
2009
|
line-height: calc(var(--spacing) * 4);
|
|
@@ -1975,6 +2048,10 @@
|
|
|
1975
2048
|
--tw-tracking: 0.05em;
|
|
1976
2049
|
letter-spacing: 0.05em;
|
|
1977
2050
|
}
|
|
2051
|
+
.tracking-\[0\.18em\] {
|
|
2052
|
+
--tw-tracking: 0.18em;
|
|
2053
|
+
letter-spacing: 0.18em;
|
|
2054
|
+
}
|
|
1978
2055
|
.tracking-tight {
|
|
1979
2056
|
--tw-tracking: var(--tracking-tight);
|
|
1980
2057
|
letter-spacing: var(--tracking-tight);
|
|
@@ -1986,6 +2063,9 @@
|
|
|
1986
2063
|
.whitespace-nowrap {
|
|
1987
2064
|
white-space: nowrap;
|
|
1988
2065
|
}
|
|
2066
|
+
.text-amber-200 {
|
|
2067
|
+
color: var(--color-amber-200);
|
|
2068
|
+
}
|
|
1989
2069
|
.text-blue-400 {
|
|
1990
2070
|
color: var(--color-blue-400);
|
|
1991
2071
|
}
|
|
@@ -2022,18 +2102,30 @@
|
|
|
2022
2102
|
.text-login-800 {
|
|
2023
2103
|
color: var(--color-login-800);
|
|
2024
2104
|
}
|
|
2105
|
+
.text-login-950 {
|
|
2106
|
+
color: var(--color-login-950);
|
|
2107
|
+
}
|
|
2025
2108
|
.text-login-text {
|
|
2026
2109
|
color: var(--color-login-text);
|
|
2027
2110
|
}
|
|
2028
2111
|
.text-login-text\! {
|
|
2029
2112
|
color: var(--color-login-text) !important;
|
|
2030
2113
|
}
|
|
2114
|
+
.text-orange-200 {
|
|
2115
|
+
color: var(--color-orange-200);
|
|
2116
|
+
}
|
|
2117
|
+
.text-red-200 {
|
|
2118
|
+
color: var(--color-red-200);
|
|
2119
|
+
}
|
|
2031
2120
|
.text-red-400 {
|
|
2032
2121
|
color: var(--color-red-400);
|
|
2033
2122
|
}
|
|
2034
2123
|
.text-red-500 {
|
|
2035
2124
|
color: var(--color-red-500);
|
|
2036
2125
|
}
|
|
2126
|
+
.text-sky-200 {
|
|
2127
|
+
color: var(--color-sky-200);
|
|
2128
|
+
}
|
|
2037
2129
|
.text-white {
|
|
2038
2130
|
color: var(--color-white);
|
|
2039
2131
|
}
|
|
@@ -2497,6 +2589,16 @@
|
|
|
2497
2589
|
}
|
|
2498
2590
|
}
|
|
2499
2591
|
}
|
|
2592
|
+
.hover\:bg-login-50\/10 {
|
|
2593
|
+
&:hover {
|
|
2594
|
+
@media (hover: hover) {
|
|
2595
|
+
background-color: color-mix(in srgb, #ededed 10%, transparent);
|
|
2596
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2597
|
+
background-color: color-mix(in oklab, var(--color-login-50) 10%, transparent);
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2500
2602
|
.hover\:bg-login-300\/20 {
|
|
2501
2603
|
&:hover {
|
|
2502
2604
|
@media (hover: hover) {
|
|
@@ -2622,6 +2724,13 @@
|
|
|
2622
2724
|
}
|
|
2623
2725
|
}
|
|
2624
2726
|
}
|
|
2727
|
+
.hover\:text-login-50 {
|
|
2728
|
+
&:hover {
|
|
2729
|
+
@media (hover: hover) {
|
|
2730
|
+
color: var(--color-login-50);
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2625
2734
|
.hover\:text-login-100 {
|
|
2626
2735
|
&:hover {
|
|
2627
2736
|
@media (hover: hover) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uibee",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0",
|
|
4
4
|
"description": "Shared components, functions and hooks for reuse across Login projects",
|
|
5
5
|
"homepage": "https://github.com/Login-Linjeforening-for-IT/uibee#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build:clean": "rm -rf dist",
|
|
27
|
-
"build:css": "node
|
|
27
|
+
"build:css": "node src/scripts/buildCss.ts",
|
|
28
28
|
"build:rewrite": "node dist/src/scripts/rewriteAlias.js",
|
|
29
29
|
"build:ts": "tsc --declaration",
|
|
30
30
|
"build": "npm run build:clean && npm run build:css && npm run build:ts && npm run build:rewrite",
|
|
@@ -32,27 +32,27 @@
|
|
|
32
32
|
"lint:fix": "eslint --fix ./src"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"next": "^16.1
|
|
35
|
+
"next": "^16.2.1",
|
|
36
36
|
"react": "^19.2.4"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
40
|
-
"@tailwindcss/postcss": "^4.2.
|
|
40
|
+
"@tailwindcss/postcss": "^4.2.2",
|
|
41
41
|
"@tailwindcss/typography": "^0.5.19",
|
|
42
|
-
"@types/node": "^25.
|
|
42
|
+
"@types/node": "^25.6.0",
|
|
43
43
|
"@types/react": "19.2.14",
|
|
44
44
|
"@types/react-dom": "^19.2.3",
|
|
45
|
-
"eslint": "^10.0
|
|
45
|
+
"eslint": "^10.2.0",
|
|
46
46
|
"glob": "^13.0.6",
|
|
47
|
-
"postcss": "^8.5.
|
|
48
|
-
"tailwindcss": "^4.2.
|
|
47
|
+
"postcss": "^8.5.10",
|
|
48
|
+
"tailwindcss": "^4.2.2",
|
|
49
49
|
"ts-node": "^10.9.2",
|
|
50
|
-
"typescript": "^
|
|
51
|
-
"typescript-eslint": "^8.
|
|
50
|
+
"typescript": "^6.0.2",
|
|
51
|
+
"typescript-eslint": "^8.58.2"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"lucide-react": "^
|
|
55
|
-
"react-dom": "19.2.
|
|
54
|
+
"lucide-react": "^1.8.0",
|
|
55
|
+
"react-dom": "19.2.5",
|
|
56
56
|
"react-markdown": "^10.1.0",
|
|
57
57
|
"remark-gfm": "^4.0.1",
|
|
58
58
|
"utilbee": "^1.4.1"
|
package/src/components/index.ts
CHANGED
|
@@ -48,4 +48,10 @@ export { default as Pagination } from './table/pagination'
|
|
|
48
48
|
export { default as MarkdownRender } from './markdownrender/markdownRender'
|
|
49
49
|
|
|
50
50
|
// Confirm
|
|
51
|
-
export { default as ConfirmPopup } from './confirm/confirmPopup'
|
|
51
|
+
export { default as ConfirmPopup } from './confirm/confirmPopup'
|
|
52
|
+
|
|
53
|
+
// Vulnerability
|
|
54
|
+
export { default as SeverityPill } from './vulnerability/severityPill'
|
|
55
|
+
|
|
56
|
+
// Layout
|
|
57
|
+
export { default as Toggle } from './layout/toggle'
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
type ToggleOption<T> = {
|
|
2
|
+
value: T
|
|
3
|
+
label?: string
|
|
4
|
+
text?: string
|
|
5
|
+
icon?: React.ReactNode
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type ToggleProps<T> = {
|
|
9
|
+
value: T
|
|
10
|
+
onChange: (value: T) => void
|
|
11
|
+
left: ToggleOption<T>
|
|
12
|
+
right: ToggleOption<T>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default function Toggle<T>({
|
|
16
|
+
value,
|
|
17
|
+
onChange,
|
|
18
|
+
left,
|
|
19
|
+
right,
|
|
20
|
+
}: ToggleProps<T>) {
|
|
21
|
+
const active = 'bg-login-200 text-login-950 shadow'
|
|
22
|
+
const idle = 'text-login-200 hover:bg-login-50/10 hover:text-login-50'
|
|
23
|
+
|
|
24
|
+
const base =
|
|
25
|
+
'flex items-center justify-center rounded-full transition gap-1'
|
|
26
|
+
|
|
27
|
+
function renderContent(opt: ToggleOption<T>) {
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
{opt.icon}
|
|
31
|
+
{opt.text && <span>{opt.text}</span>}
|
|
32
|
+
</>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const isLeftActive = value === left.value
|
|
37
|
+
const isRightActive = value === right.value
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className='flex items-center rounded-full border border-login-100/10 bg-login-50/5 p-1'>
|
|
41
|
+
<button
|
|
42
|
+
type='button'
|
|
43
|
+
onClick={() => onChange(left.value)}
|
|
44
|
+
aria-label={left.label ?? left.text}
|
|
45
|
+
aria-pressed={isLeftActive}
|
|
46
|
+
className={`${base} px-2 h-7 ${isLeftActive ? active : idle}`}
|
|
47
|
+
>
|
|
48
|
+
{renderContent(left)}
|
|
49
|
+
</button>
|
|
50
|
+
|
|
51
|
+
<button
|
|
52
|
+
type='button'
|
|
53
|
+
onClick={() => onChange(right.value)}
|
|
54
|
+
aria-label={right.label ?? right.text}
|
|
55
|
+
aria-pressed={isRightActive}
|
|
56
|
+
className={`${base} px-2 h-7 ${isRightActive ? active : idle}`}
|
|
57
|
+
>
|
|
58
|
+
{renderContent(right)}
|
|
59
|
+
</button>
|
|
60
|
+
</div>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type SeverityLevel = 'critical' | 'high' | 'medium' | 'low' | 'unknown'
|
|
2
|
+
|
|
3
|
+
export const severityLabel: Record<SeverityLevel, string> = {
|
|
4
|
+
critical: 'Critical',
|
|
5
|
+
high: 'High',
|
|
6
|
+
medium: 'Medium',
|
|
7
|
+
low: 'Low',
|
|
8
|
+
unknown: 'Unknown',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const severityClasses: Record<SeverityLevel, string> = {
|
|
12
|
+
critical: 'border-red-400/25 bg-red-500/10 text-red-200',
|
|
13
|
+
high: 'border-orange-400/25 bg-orange-500/10 text-orange-200',
|
|
14
|
+
medium: 'border-amber-400/25 bg-amber-500/10 text-amber-200',
|
|
15
|
+
low: 'border-sky-400/25 bg-sky-500/10 text-sky-200',
|
|
16
|
+
unknown: 'border-login-100/10 bg-login-50/5 text-login-200',
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { severityClasses, severityLabel } from './constants'
|
|
2
|
+
|
|
3
|
+
type SeverityLevel = 'critical' | 'high' | 'medium' | 'low' | 'unknown'
|
|
4
|
+
|
|
5
|
+
type SeverityPillProps = {
|
|
6
|
+
severity: SeverityLevel
|
|
7
|
+
count: number
|
|
8
|
+
compact?: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function SeverityPill({ severity, count, compact = false }: SeverityPillProps) {
|
|
12
|
+
if (count === 0) {
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className={`rounded-xl border ${compact ? 'px-3 py-2' : 'p-3'} ${severityClasses[severity]}`}>
|
|
18
|
+
<div className='text-[11px] font-medium uppercase tracking-[0.18em]'>{severityLabel[severity]}</div>
|
|
19
|
+
<div className={`${compact ? 'mt-1 text-sm' : 'mt-2 text-lg'} font-semibold`}>{count}</div>
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
}
|