This commit is contained in:
Stefan Pejcic
2024-11-07 19:03:37 +01:00
parent c6df945ed5
commit 09f9f9502d
2472 changed files with 620417 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
import React, { type ReactNode } from "react";
import { Route, Routes } from "react-router-dom";
import {
render,
TestWrapper,
type ITestWrapperProps,
act,
MockLegacyRouterProvider,
} from "@test";
import { Breadcrumb } from "./";
import { breadcrumbTests } from "@refinedev/ui-tests";
const renderBreadcrumb = (
children: ReactNode,
wrapperProps: ITestWrapperProps = {},
) => {
return render(
<Routes>
<Route path="/:resource/:action" element={children} />
</Routes>,
{
wrapper: TestWrapper({
...wrapperProps,
legacyRouterProvider: MockLegacyRouterProvider,
}),
},
);
};
const DummyDashboard = () => <div>Dashboard</div>;
describe("Breadcrumb", () => {
beforeAll(() => {
jest.spyOn(console, "warn").mockImplementation(jest.fn());
});
breadcrumbTests.bind(this)(Breadcrumb);
it("should render home icon", async () => {
const { container } = renderBreadcrumb(<Breadcrumb />, {
resources: [{ name: "posts" }],
routerInitialEntries: ["/posts/create"],
DashboardPage: DummyDashboard,
});
expect(container.querySelector("svg")).toBeTruthy();
});
it("should not render home icon with 'showhHome' props", async () => {
const { container } = renderBreadcrumb(<Breadcrumb showHome={false} />, {
resources: [{ name: "posts" }],
routerInitialEntries: ["/posts/create"],
DashboardPage: DummyDashboard,
});
expect(container.querySelector("svg")).toBeFalsy();
});
it("should render breadcrumb items", async () => {
const { getByText } = renderBreadcrumb(<Breadcrumb />, {
resources: [{ name: "posts" }],
routerInitialEntries: ["/posts/create"],
});
getByText("Posts");
getByText("Create");
});
});

View File

@@ -0,0 +1,83 @@
import React from "react";
import {
matchResourceFromRoute,
useBreadcrumb,
useLink,
useRefineContext,
useResource,
useRouterContext,
useRouterType,
} from "@refinedev/core";
import type { RefineBreadcrumbProps } from "@refinedev/ui-types";
import {
Text,
Breadcrumbs,
type BreadcrumbsProps as MantineBreadcrumbProps,
Anchor,
Group,
} from "@mantine/core";
import { IconHome } from "@tabler/icons-react";
export type BreadcrumbProps = RefineBreadcrumbProps<MantineBreadcrumbProps>;
export const Breadcrumb: React.FC<BreadcrumbProps> = ({
breadcrumbProps,
showHome = true,
hideIcons = false,
meta,
}) => {
const routerType = useRouterType();
const { breadcrumbs } = useBreadcrumb({ meta });
const Link = useLink();
const { Link: LegacyLink } = useRouterContext();
const { hasDashboard } = useRefineContext();
const { resources } = useResource();
const rootRouteResource = matchResourceFromRoute("/", resources);
const ActiveLink = routerType === "legacy" ? LegacyLink : Link;
if (breadcrumbs.length === 1) {
return null;
}
return (
<Breadcrumbs
aria-label="breadcrumb"
styles={{
separator: { marginRight: 8, marginLeft: 8, color: "dimgray" },
}}
{...breadcrumbProps}
>
{showHome && (hasDashboard || rootRouteResource.found) && (
<Anchor component={ActiveLink as any} color="dimmed" to="/">
{rootRouteResource?.resource?.meta?.icon ?? <IconHome size={18} />}
</Anchor>
)}
{breadcrumbs.map(({ label, icon, href }) => {
return (
<Group key={label} spacing={4} align="center" noWrap>
{!hideIcons && icon}
{href ? (
<Anchor
component={ActiveLink as any}
color="dimmed"
to={href}
size="sm"
>
{label}
</Anchor>
) : (
<Text color="dimmed" size="sm">
{label}
</Text>
)}
</Group>
);
})}
</Breadcrumbs>
);
};