From 72822aea2ba4360a7b783019e2ac8fe9575be00e Mon Sep 17 00:00:00 2001
From: Sasha
Date: Thu, 16 Jan 2025 10:24:47 +0100
Subject: [PATCH] fix: UI fixes for statistics and merchant monitoring report
pages (#2965)
---
.../src/pages/Home/Home.page.tsx | 1 -
.../MerchantMonitoringTable/columns.tsx | 67 ++++++++--------
.../src/pages/Statistics/Statistics.page.tsx | 1 +
.../PortfolioRiskStatistics.tsx | 32 ++++----
.../usePortfolioRiskStatisticsLogic.tsx | 22 ++----
apps/kyb-app/CHANGELOG.md | 7 ++
apps/kyb-app/package.json | 4 +-
packages/react-pdf-toolkit/CHANGELOG.md | 7 ++
packages/react-pdf-toolkit/package.json | 4 +-
packages/ui/CHANGELOG.md | 6 ++
packages/ui/package.json | 2 +-
.../ui/src/components/atoms/Chart/Chart.tsx | 18 +++--
.../molecules/ContentTooltip/index.ts | 1 +
packages/ui/src/components/molecules/index.ts | 1 +
.../WebsiteCredibility/WebsiteCredibility.tsx | 78 +++++++------------
pnpm-lock.yaml | 12 +--
16 files changed, 131 insertions(+), 132 deletions(-)
create mode 100644 packages/ui/src/components/molecules/ContentTooltip/index.ts
diff --git a/apps/backoffice-v2/src/pages/Home/Home.page.tsx b/apps/backoffice-v2/src/pages/Home/Home.page.tsx
index 1798043426..c4b6160ad3 100644
--- a/apps/backoffice-v2/src/pages/Home/Home.page.tsx
+++ b/apps/backoffice-v2/src/pages/Home/Home.page.tsx
@@ -53,7 +53,6 @@ export const Home: FunctionComponent = () => {
{/* */}
{/* */}
{/* */}
- {/* */}
{/* */}
{/**/}
{(isDemo || isExample) && }
diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx b/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx
index 9f5fa2d8e4..506e1ec834 100644
--- a/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx
+++ b/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx
@@ -1,34 +1,33 @@
import dayjs from 'dayjs';
-import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
+import utc from 'dayjs/plugin/utc';
// Add these plugins to dayjs
dayjs.extend(utc);
dayjs.extend(timezone);
-import { createColumnHelper } from '@tanstack/react-table';
import { TBusinessReport } from '@/domains/business-reports/fetchers';
+import { createColumnHelper } from '@tanstack/react-table';
import { titleCase } from 'string-ts';
+import { CopyToClipboardButton } from '@/common/components/atoms/CopyToClipboardButton/CopyToClipboardButton';
+import { IndicatorCircle } from '@/common/components/atoms/IndicatorCircle/IndicatorCircle';
+import { useEllipsesWithTitle } from '@/common/hooks/useEllipsesWithTitle/useEllipsesWithTitle';
import { ctw } from '@/common/utils/ctw/ctw';
+import {
+ MERCHANT_REPORT_STATUSES_MAP,
+ MERCHANT_REPORT_TYPES_MAP,
+} from '@/domains/business-reports/constants';
import { getSeverityFromRiskScore } from '@ballerine/common';
import {
Badge,
CheckCircle,
+ ContentTooltip,
severityToClassName,
TextWithNAFallback,
WarningFilledSvg,
} from '@ballerine/ui';
-import { useEllipsesWithTitle } from '@/common/hooks/useEllipsesWithTitle/useEllipsesWithTitle';
-import { CopyToClipboardButton } from '@/common/components/atoms/CopyToClipboardButton/CopyToClipboardButton';
import { Minus } from 'lucide-react';
-import {
- MERCHANT_REPORT_STATUSES_MAP,
- MERCHANT_REPORT_TYPES_MAP,
-} from '@/domains/business-reports/constants';
-import React from 'react';
-import { IndicatorCircle } from '@/common/components/atoms/IndicatorCircle/IndicatorCircle';
-import { TooltipTrigger, TooltipContent, Tooltip } from '@ballerine/ui';
const columnHelper = createColumnHelper();
@@ -93,9 +92,19 @@ export const columns = [
}),
columnHelper.accessor('monitoringStatus', {
cell: ({ getValue }) => {
- return getValue() ? (
-
-
+ const value = getValue();
+
+ return (
+ This merchant is {!value && 'not '}subscribed to recurring ongoing monitoring
+ }
+ props={{
+ tooltipTrigger: { className: 'flex w-full justify-center' },
+ tooltipContent: { align: 'center', side: 'top' },
+ }}
+ >
+ {value ? (
-
-
- This website is actively monitored for changes on a recurring basis
-
-
- ) : (
-
-
+ ) : (
-
- This website is not currently monitored for changes
-
+ )}
+
);
},
header: () => (
-
-
- Monitored
-
-
- Indicates whether this website is being monitored for changes
-
-
+ Indicates whether the merchant is subscribed to ongoing monitoring}
+ props={{
+ tooltipContent: { align: 'center', side: 'top' },
+ }}
+ >
+ Monitored
+
),
}),
columnHelper.accessor('reportType', {
diff --git a/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx b/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx
index eef3733fff..71360b469f 100644
--- a/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx
+++ b/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx
@@ -31,6 +31,7 @@ export const Statistics: FunctionComponent = () => {
removedMerchantsCount={data.removedMerchantsCount}
/>
diff --git a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx
index 20e5a2d8ce..9720bd3c6e 100644
--- a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx
+++ b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx
@@ -1,9 +1,13 @@
+import { buttonVariants, WarningFilledSvg } from '@ballerine/ui';
import { FunctionComponent } from 'react';
+import { Link } from 'react-router-dom';
+import { Cell, Pie, PieChart } from 'recharts';
+import { titleCase } from 'string-ts';
+import { z } from 'zod';
+
import { Card } from '@/common/components/atoms/Card/Card';
-import { CardHeader } from '@/common/components/atoms/Card/Card.Header';
import { CardContent } from '@/common/components/atoms/Card/Card.Content';
-import { Cell, Pie, PieChart } from 'recharts';
-import { ctw } from '@/common/utils/ctw/ctw';
+import { CardHeader } from '@/common/components/atoms/Card/Card.Header';
import {
Table,
TableBody,
@@ -12,16 +16,15 @@ import {
TableHeader,
TableRow,
} from '@/common/components/atoms/Table';
-import { titleCase } from 'string-ts';
-import { usePortfolioRiskStatisticsLogic } from '@/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic';
-import { z } from 'zod';
+import { ctw } from '@/common/utils/ctw/ctw';
import { MetricsResponseSchema } from '@/domains/business-reports/hooks/queries/useBusinessReportMetricsQuery/useBusinessReportMetricsQuery';
-import { Link } from 'react-router-dom';
-import { buttonVariants, WarningFilledSvg } from '@ballerine/ui';
+import { usePortfolioRiskStatisticsLogic } from '@/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic';
export const PortfolioRiskStatistics: FunctionComponent<
- Pick, 'riskLevelCounts' | 'violationCounts'>
-> = ({ riskLevelCounts, violationCounts }) => {
+ Pick, 'riskLevelCounts' | 'violationCounts'> & {
+ userSelectedDate: Date;
+ }
+> = ({ riskLevelCounts, violationCounts, userSelectedDate }) => {
const {
riskLevelToFillColor,
parent,
@@ -30,10 +33,11 @@ export const PortfolioRiskStatistics: FunctionComponent<
filteredRiskIndicators,
locale,
navigate,
+ alertedReports,
from,
to,
- alertedReports,
} = usePortfolioRiskStatisticsLogic({
+ userSelectedDate,
violationCounts,
});
@@ -84,7 +88,9 @@ export const PortfolioRiskStatistics: FunctionComponent<
'cursor-pointer outline-none',
)}
onClick={() =>
- navigate(`/${locale}/merchant-monitoring?riskLevels[0]=${riskLevel}`)
+ navigate(
+ `/${locale}/merchant-monitoring?riskLevels[0]=${riskLevel}&from=${from}&to=${to}`,
+ )
}
/>
))}
@@ -135,7 +141,7 @@ export const PortfolioRiskStatistics: FunctionComponent<
diff --git a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx
index 2689c99a4e..ce870cf7b5 100644
--- a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx
+++ b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx
@@ -16,7 +16,8 @@ import { useBusinessReportsQuery } from '@/domains/business-reports/hooks/querie
export const usePortfolioRiskStatisticsLogic = ({
violationCounts,
-}: Pick, 'violationCounts'>) => {
+ userSelectedDate,
+}: Pick, 'violationCounts'> & { userSelectedDate: Date }) => {
const [parent] = useAutoAnimate();
const [riskIndicatorsSorting, setRiskIndicatorsSorting] = useState('desc');
const onSortRiskIndicators = useCallback(
@@ -48,23 +49,14 @@ export const usePortfolioRiskStatisticsLogic = ({
);
const locale = useLocale();
const navigate = useNavigate();
- const getLast30DaysDateRange = () => {
- const today = dayjs();
- const thirtyDaysAgo = today.subtract(30, 'day');
- return {
- from: thirtyDaysAgo.format('YYYY-MM-DD'),
- to: today.format('YYYY-MM-DD'),
- };
- };
-
- const last30DaysDateRange = getLast30DaysDateRange();
- const [{ from }] = useZodSearchParams(StatisticsSearchSchema);
+ const from = dayjs(userSelectedDate).format('YYYY-MM-DD');
+ const to = dayjs(userSelectedDate).add(1, 'month').format('YYYY-MM-DD');
const { data: businessReports } = useBusinessReportsQuery({
isAlert: true,
from,
- to: dayjs(from).add(1, 'month').format('YYYY-MM-DD'),
+ to,
});
const alertedReports = businessReports?.totalItems ?? 0;
@@ -79,8 +71,8 @@ export const usePortfolioRiskStatisticsLogic = ({
filteredRiskIndicators,
locale,
navigate,
- from: last30DaysDateRange.from,
- to: last30DaysDateRange.to,
+ from,
+ to,
alertedReports,
};
};
diff --git a/apps/kyb-app/CHANGELOG.md b/apps/kyb-app/CHANGELOG.md
index 4725d46091..3ce302e21d 100644
--- a/apps/kyb-app/CHANGELOG.md
+++ b/apps/kyb-app/CHANGELOG.md
@@ -1,5 +1,12 @@
# kyb-app
+## 0.3.110
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/ui@0.5.63
+
## 0.3.109
### Patch Changes
diff --git a/apps/kyb-app/package.json b/apps/kyb-app/package.json
index 1d3c40e3d8..4e4d538006 100644
--- a/apps/kyb-app/package.json
+++ b/apps/kyb-app/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/kyb-app",
"private": true,
- "version": "0.3.109",
+ "version": "0.3.110",
"type": "module",
"scripts": {
"dev": "vite",
@@ -19,7 +19,7 @@
"@ballerine/blocks": "0.2.32",
"@ballerine/common": "^0.9.66",
"@ballerine/workflow-browser-sdk": "0.6.85",
- "@ballerine/ui": "0.5.62",
+ "@ballerine/ui": "0.5.63",
"@lukemorales/query-key-factory": "^1.0.3",
"@radix-ui/react-icons": "^1.3.0",
"@rjsf/core": "^5.9.0",
diff --git a/packages/react-pdf-toolkit/CHANGELOG.md b/packages/react-pdf-toolkit/CHANGELOG.md
index 0256f35422..ee9f9a4456 100644
--- a/packages/react-pdf-toolkit/CHANGELOG.md
+++ b/packages/react-pdf-toolkit/CHANGELOG.md
@@ -1,5 +1,12 @@
# @ballerine/react-pdf-toolkit
+## 1.2.63
+
+### Patch Changes
+
+- Updated dependencies
+ - @ballerine/ui@0.5.63
+
## 1.2.62
### Patch Changes
diff --git a/packages/react-pdf-toolkit/package.json b/packages/react-pdf-toolkit/package.json
index ef1f896b28..39661eb59a 100644
--- a/packages/react-pdf-toolkit/package.json
+++ b/packages/react-pdf-toolkit/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/react-pdf-toolkit",
"private": false,
- "version": "1.2.62",
+ "version": "1.2.63",
"types": "./dist/build.d.ts",
"main": "./dist/react-pdf-toolkit.js",
"module": "./dist/react-pdf-toolkit.mjs",
@@ -27,7 +27,7 @@
},
"dependencies": {
"@ballerine/config": "^1.1.30",
- "@ballerine/ui": "0.5.62",
+ "@ballerine/ui": "0.5.63",
"@react-pdf/renderer": "^3.1.14",
"@sinclair/typebox": "^0.31.7",
"ajv": "^8.12.0",
diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md
index a99bd0b47a..e93634bd7e 100644
--- a/packages/ui/CHANGELOG.md
+++ b/packages/ui/CHANGELOG.md
@@ -1,5 +1,11 @@
# @ballerine/ui
+## 0.5.63
+
+### Patch Changes
+
+- Export ContentTooltip component
+
## 0.5.62
### Patch Changes
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 2bd8265e07..ae8b3c0e27 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -1,7 +1,7 @@
{
"name": "@ballerine/ui",
"private": false,
- "version": "0.5.62",
+ "version": "0.5.63",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/packages/ui/src/components/atoms/Chart/Chart.tsx b/packages/ui/src/components/atoms/Chart/Chart.tsx
index b3e74fb40b..f82e968c2c 100644
--- a/packages/ui/src/components/atoms/Chart/Chart.tsx
+++ b/packages/ui/src/components/atoms/Chart/Chart.tsx
@@ -1,6 +1,7 @@
import { ctw } from '@/common/utils/ctw';
import * as React from 'react';
import * as RechartsPrimitive from 'recharts';
+import { ValueType } from 'recharts/types/component/DefaultTooltipContent';
// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: '', dark: '.dark' } as const;
@@ -100,6 +101,7 @@ const ChartTooltipContent = React.forwardRef<
indicator?: 'line' | 'dot' | 'dashed';
nameKey?: string;
labelKey?: string;
+ valueRender?: (value: ValueType) => React.ReactNode;
}
>(
(
@@ -110,6 +112,7 @@ const ChartTooltipContent = React.forwardRef<
indicator = 'dot',
hideLabel = false,
hideIndicator = false,
+ valueRender,
label,
labelFormatter,
labelClassName,
@@ -217,11 +220,12 @@ const ChartTooltipContent = React.forwardRef<
{itemConfig?.label || item.name}
- {item.value && (
-
- {item.value.toLocaleString()}
-
- )}
+ {item.value &&
+ (valueRender?.(item.value) ?? (
+
+ {item.value.toLocaleString()}
+
+ ))}
>
)}
@@ -291,7 +295,7 @@ const ChartLegendContent = React.forwardRef<
ChartLegendContent.displayName = 'ChartLegend';
// Helper to extract item config from a payload.
-function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {
+const getPayloadConfigFromPayload = (config: ChartConfig, payload: unknown, key: string) => {
if (typeof payload !== 'object' || payload === null) {
return undefined;
}
@@ -314,7 +318,7 @@ function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key:
}
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];
-}
+};
export {
ChartContainer,
diff --git a/packages/ui/src/components/molecules/ContentTooltip/index.ts b/packages/ui/src/components/molecules/ContentTooltip/index.ts
new file mode 100644
index 0000000000..086008aab9
--- /dev/null
+++ b/packages/ui/src/components/molecules/ContentTooltip/index.ts
@@ -0,0 +1 @@
+export * from './ContentTooltip';
diff --git a/packages/ui/src/components/molecules/index.ts b/packages/ui/src/components/molecules/index.ts
index 1841c425ea..7a5ca9100b 100644
--- a/packages/ui/src/components/molecules/index.ts
+++ b/packages/ui/src/components/molecules/index.ts
@@ -1,3 +1,4 @@
+export * from './ContentTooltip';
export * from './JsonDialog';
export * from './inputs';
export * from './ErrorsList';
diff --git a/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx b/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx
index f011a255fa..546d0f2628 100644
--- a/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx
+++ b/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx
@@ -1,13 +1,24 @@
+import { ctw } from '@/common';
import { Card, CardContent, CardHeader } from '@/components';
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/atoms';
+import {
+ CardDescription,
+ ChartContainer,
+ ChartTooltip,
+ ChartTooltipContent,
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from '@/components/atoms';
import { BallerineLink } from '@/components/atoms/BallerineLink/BallerineLink';
-import { ctw } from '@/common';
import { ContentTooltip } from '@/components/molecules/ContentTooltip/ContentTooltip';
import { RiskIndicators } from '@/components/molecules/RiskIndicators/RiskIndicators';
import dayjs from 'dayjs';
-import { InfoIcon, TrendingDown } from 'lucide-react';
+import { InfoIcon } from 'lucide-react';
import { FunctionComponent, useMemo } from 'react';
import {
+ Area,
+ AreaChart,
CartesianGrid,
Cell,
Legend,
@@ -18,10 +29,6 @@ import {
YAxis,
} from 'recharts';
import { capitalize } from 'string-ts';
-import { TrendingUp } from 'lucide-react';
-import { Area, AreaChart } from 'recharts';
-import { CardDescription, CardFooter } from '@/components/atoms';
-import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/atoms';
const engagementMetricsMapper = {
'Time on site': {
@@ -81,23 +88,6 @@ export const WebsiteCredibility: FunctionComponent<{
.map(({ label, value }) => ({ label, value: parseFloat(value.toFixed(2)) }));
}, [trafficAnalysis.trafficSources]);
- const calculateTrend = (data: Array<{ label: string; value: string }>) => {
- if (data.length < 2) {
- return { direction: 'No trend data', percentage: 0 };
- }
-
- const lastMonthValue = parseInt(data[data.length - 1]?.value ?? '0');
- const previousMonthValue = parseInt(data[data.length - 2]?.value ?? '0');
- const percentageChange = ((lastMonthValue - previousMonthValue) / previousMonthValue) * 100;
- const direction = lastMonthValue > previousMonthValue ? 'up' : 'down';
-
- return { direction, percentage: Math.abs(percentageChange) };
- };
-
- const trend = calculateTrend(
- trafficAnalysis.montlyVisitsIndicators.map(({ label, value }) => ({ label, value })),
- );
-
return (
@@ -194,8 +184,8 @@ export const WebsiteCredibility: FunctionComponent<{
}
+ content={
+
(
+
+ {Intl.NumberFormat('en').format(Number(value))}
+
+ )}
+ />
+ }
/>
)}
-
-
-
-
- {trend.direction !== 'No trend data' && (
- <>
- {trend.direction === 'up' ? (
-
- ) : (
-
- )}
- {`Trending ${trend.direction} by ${trend.percentage.toFixed(
- 1,
- )}% this month`}
- >
- )}
-
-
-
-
- {/*
-
*/}
Traffic Sources
@@ -468,9 +445,6 @@ export const WebsiteCredibility: FunctionComponent<{
-
- {/*
-
*/}
);
};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9de65bc44b..86f7dda3fa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -536,7 +536,7 @@ importers:
specifier: ^0.9.66
version: link:../../packages/common
'@ballerine/ui':
- specifier: 0.5.62
+ specifier: 0.5.63
version: link:../../packages/ui
'@ballerine/workflow-browser-sdk':
specifier: 0.6.85
@@ -1516,7 +1516,7 @@ importers:
specifier: ^1.1.30
version: link:../config
'@ballerine/ui':
- specifier: 0.5.62
+ specifier: 0.5.63
version: link:../ui
'@react-pdf/renderer':
specifier: ^3.1.14
@@ -20306,7 +20306,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.3)
'@types/babel__core': 7.20.4
react-refresh: 0.14.0
- vite: 4.5.3(@types/node@18.17.19)
+ vite: 4.5.3(@types/node@20.9.2)
transitivePeerDependencies:
- supports-color
dev: true
@@ -38536,7 +38536,7 @@ packages:
strip-ansi: 6.0.1
tiny-invariant: 1.3.1
typescript: 5.1.6
- vite: 4.5.3(@types/node@18.17.19)
+ vite: 4.5.3(@types/node@20.9.2)
vscode-languageclient: 7.0.0
vscode-languageserver: 7.0.0
vscode-languageserver-textdocument: 1.0.11
@@ -38667,7 +38667,7 @@ packages:
kolorist: 1.8.0
sirv: 2.0.3
ufo: 1.3.2
- vite: 4.5.3(@types/node@18.17.19)
+ vite: 4.5.3(@types/node@20.9.2)
transitivePeerDependencies:
- rollup
- supports-color
@@ -38746,7 +38746,7 @@ packages:
debug: 4.3.4(supports-color@8.1.1)
globrex: 0.1.2
tsconfck: 2.1.2(typescript@5.1.6)
- vite: 4.5.3(@types/node@18.17.19)
+ vite: 4.5.3(@types/node@20.9.2)
transitivePeerDependencies:
- supports-color
- typescript