refactor: remove @numeric-text/react dependency and implement NumericText component

This commit is contained in:
hamster1963
2026-07-05 13:43:41 +08:00
parent 056c357b6e
commit 7424b2bfde
9 changed files with 35 additions and 44 deletions
-1
View File
@@ -27,7 +27,6 @@
"dependencies": { "dependencies": {
"@fontsource/inter": "5.2.8", "@fontsource/inter": "5.2.8",
"@heroicons/react": "2.2.0", "@heroicons/react": "2.2.0",
"@numeric-text/react": "^0.1.4",
"@radix-ui/react-accordion": "1.2.13", "@radix-ui/react-accordion": "1.2.13",
"@radix-ui/react-checkbox": "1.3.4", "@radix-ui/react-checkbox": "1.3.4",
"@radix-ui/react-dialog": "^1.1.18", "@radix-ui/react-dialog": "^1.1.18",
-18
View File
@@ -14,9 +14,6 @@ importers:
'@heroicons/react': '@heroicons/react':
specifier: 2.2.0 specifier: 2.2.0
version: 2.2.0(react@19.2.7) version: 2.2.0(react@19.2.7)
'@numeric-text/react':
specifier: ^0.1.4
version: 0.1.4(react@19.2.7)
'@radix-ui/react-accordion': '@radix-ui/react-accordion':
specifier: 1.2.13 specifier: 1.2.13
version: 1.2.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) version: 1.2.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
@@ -394,14 +391,6 @@ packages:
'@emnapi/core': ^1.7.1 '@emnapi/core': ^1.7.1
'@emnapi/runtime': ^1.7.1 '@emnapi/runtime': ^1.7.1
'@numeric-text/core@0.1.4':
resolution: {integrity: sha512-tMaH5u/kdpw3AP+XJMnDWyq39zVHoP80NCLTFwzVept64dIAMKBNLlYtUK0+EULiyFg6IiSwswmc9tMukV1tLw==}
'@numeric-text/react@0.1.4':
resolution: {integrity: sha512-i1t18jSzn168nl9jYrC+W1FlPexjy0dbAa9bofykaL44ogu+puLg2f5roVA3xOUgjL6bSojv+wKUA/ZRRshwEw==}
peerDependencies:
react: ^18 || ^19
'@oxc-project/types@0.137.0': '@oxc-project/types@0.137.0':
resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==}
@@ -2270,13 +2259,6 @@ snapshots:
'@tybys/wasm-util': 0.10.3 '@tybys/wasm-util': 0.10.3
optional: true optional: true
'@numeric-text/core@0.1.4': {}
'@numeric-text/react@0.1.4(react@19.2.7)':
dependencies:
'@numeric-text/core': 0.1.4
react: 19.2.7
'@oxc-project/types@0.137.0': {} '@oxc-project/types@0.137.0': {}
'@radix-ui/number@1.1.2': {} '@radix-ui/number@1.1.2': {}
+1 -1
View File
@@ -1,4 +1,3 @@
import NumericText from "@numeric-text/react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { ImageMinus } from "lucide-react"; import { ImageMinus } from "lucide-react";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
@@ -16,6 +15,7 @@ import { cn } from "@/lib/utils";
import AnimateCountClient from "./AnimatedCount"; import AnimateCountClient from "./AnimatedCount";
import { LanguageSwitcher } from "./LanguageSwitcher"; import { LanguageSwitcher } from "./LanguageSwitcher";
import { Loader, LoadingSpinner } from "./loading/Loader"; import { Loader, LoadingSpinner } from "./loading/Loader";
import NumericText from "./NumericText";
import { SearchButton } from "./SearchButton"; import { SearchButton } from "./SearchButton";
import { Button } from "./ui/button"; import { Button } from "./ui/button";
+30
View File
@@ -0,0 +1,30 @@
import type { ComponentPropsWithoutRef } from "react";
type NumericTextTransition = {
duration?: number;
easing?: string;
};
type NumericTextProps = Omit<ComponentPropsWithoutRef<"span">, "children"> & {
animated?: boolean;
respectMotionPreference?: boolean;
transition?: NumericTextTransition;
trend?: -1 | 0 | 1;
value: number | string;
};
export default function NumericText({
animated,
respectMotionPreference,
transition,
trend,
value,
...spanProps
}: NumericTextProps) {
void animated;
void respectMotionPreference;
void transition;
void trend;
return <span {...spanProps}>{value}</span>;
}
+1 -1
View File
@@ -1,4 +1,3 @@
import NumericText from "@numeric-text/react";
import countries from "i18n-iso-countries"; import countries from "i18n-iso-countries";
import enLocale from "i18n-iso-countries/langs/en.json"; import enLocale from "i18n-iso-countries/langs/en.json";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -12,6 +11,7 @@ import { Card, CardContent } from "@/components/ui/card";
import { useWebSocketContext } from "@/hooks/use-websocket-context"; import { useWebSocketContext } from "@/hooks/use-websocket-context";
import { formatBytes } from "@/lib/format"; import { formatBytes } from "@/lib/format";
import { cn, formatNezhaInfo } from "@/lib/utils"; import { cn, formatNezhaInfo } from "@/lib/utils";
import NumericText from "./NumericText";
import { import {
Accordion, Accordion,
AccordionContent, AccordionContent,
+1 -1
View File
@@ -2,12 +2,12 @@ import {
ArrowDownCircleIcon, ArrowDownCircleIcon,
ArrowUpCircleIcon, ArrowUpCircleIcon,
} from "@heroicons/react/20/solid"; } from "@heroicons/react/20/solid";
import NumericText from "@numeric-text/react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { useStatus } from "@/hooks/use-status"; import { useStatus } from "@/hooks/use-status";
import { formatBytes } from "@/lib/format"; import { formatBytes } from "@/lib/format";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import NumericText from "./NumericText";
type ServerOverviewProps = { type ServerOverviewProps = {
online: number; online: number;
+1 -11
View File
@@ -1,6 +1,6 @@
import { fireEvent, render, screen } from "@testing-library/react"; import { fireEvent, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it } from "vitest";
import AnimateCountClient, { AnimateCount } from "@/components/AnimatedCount"; import AnimateCountClient, { AnimateCount } from "@/components/AnimatedCount";
import ErrorBoundary from "@/components/ErrorBoundary"; import ErrorBoundary from "@/components/ErrorBoundary";
import ChartSkeleton from "@/components/loading/ChartSkeleton"; import ChartSkeleton from "@/components/loading/ChartSkeleton";
@@ -14,16 +14,6 @@ import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
vi.mock("@numeric-text/react", () => ({
default: ({
className,
value,
}: {
className?: string;
value: string | number;
}) => <span className={className}>{value}</span>,
}));
import { CommandProvider } from "@/context/command-provider"; import { CommandProvider } from "@/context/command-provider";
import { StatusProvider } from "@/context/status-provider"; import { StatusProvider } from "@/context/status-provider";
import { useCommand } from "@/hooks/use-command"; import { useCommand } from "@/hooks/use-command";
+1 -7
View File
@@ -21,12 +21,6 @@ const headerMocks = vi.hoisted(() => ({
updateBackground: vi.fn(), updateBackground: vi.fn(),
})); }));
vi.mock("@numeric-text/react", () => ({
default: ({ value }: { value: string | number }) => (
<span data-testid="numeric-text">{value}</span>
),
}));
vi.mock("@/hooks/use-background", () => ({ vi.mock("@/hooks/use-background", () => ({
useBackground: () => ({ useBackground: () => ({
backgroundImage: headerMocks.backgroundImage, backgroundImage: headerMocks.backgroundImage,
@@ -150,7 +144,7 @@ describe("Header", () => {
); );
expect(screen.getAllByRole("link", { name: "Docs" })).toHaveLength(2); expect(screen.getAllByRole("link", { name: "Docs" })).toHaveLength(2);
expect(await screen.findAllByText("dashboard")).toHaveLength(2); expect(await screen.findAllByText("dashboard")).toHaveLength(2);
expect(screen.getByTestId("numeric-text")).toHaveTextContent("4"); expect(screen.getByText("online").closest("button")).toHaveTextContent("4");
expect(screen.getByText("online")).toBeInTheDocument(); expect(screen.getByText("online")).toBeInTheDocument();
await waitFor(() => { await waitFor(() => {
@@ -14,10 +14,6 @@ const websocketMocks = vi.hoisted(() => ({
} | null, } | null,
})); }));
vi.mock("@numeric-text/react", () => ({
default: ({ value }: { value: string | number }) => <span>{value}</span>,
}));
vi.mock("@/hooks/use-websocket-context", () => ({ vi.mock("@/hooks/use-websocket-context", () => ({
useWebSocketContext: () => websocketMocks, useWebSocketContext: () => websocketMocks,
})); }));