fork refine

This commit is contained in:
Stefan Pejcic
2024-02-05 10:23:04 +01:00
parent 3fffde9a8f
commit 8496a83edb
3634 changed files with 715528 additions and 2 deletions

View File

@@ -0,0 +1,7 @@
import React from "react";
import { LayoutProps } from "../../../interfaces";
export const DefaultLayout: React.FC<LayoutProps> = ({ children }) => {
return <div>{children}</div>;
};

View File

@@ -0,0 +1,186 @@
import React from "react";
import "@testing-library/jest-dom/extend-expect";
import { LayoutWrapper } from "@components/layoutWrapper";
import {
render,
TestWrapper,
MockJSONServer,
mockLegacyRouterProvider,
} from "@test";
import { defaultRefineOptions } from "@contexts/refine";
import { IRefineContextProvider } from "../../contexts/refine/IRefineContext";
import { LayoutProps } from "../../interfaces";
const renderWithRefineContext = (
children: React.ReactNode,
refineProvider: IRefineContextProvider,
) => {
return render(<>{children}</>, {
wrapper: TestWrapper({
dataProvider: MockJSONServer,
resources: [{ name: "posts", route: "posts" }],
legacyRouterProvider: mockLegacyRouterProvider(),
refineProvider,
}),
});
};
describe("LayoutWrapper", () => {
it("LayoutWrapper successfully pass the custom components to Layout component as a props", () => {
const customSiderContent = "customSiderContent";
const CustomSider = () => <p>{customSiderContent}</p>;
const customHeaderContent = "customHeaderContent";
const CustomHeader = () => <p>{customHeaderContent}</p>;
const customFooterContent = "customFooterContent";
const CustomFooter = () => <p>{customFooterContent}</p>;
const customOffLayoutAreaContent = "customOffLayoutAreaContent";
const CustomOffLayoutArea = () => <p>{customOffLayoutAreaContent}</p>;
const customTitleContent = "customTitleContent";
const CustomTitle = () => <p>{customTitleContent}</p>;
const CustomLayout: React.FC<LayoutProps> = ({
Header,
Sider,
Footer,
OffLayoutArea,
Title,
children,
}) => {
return (
<div>
{Header && <Header />}
{Title && <Title collapsed={true} />}
{Sider && <Sider />}
{children}
{Footer && <Footer />}
{OffLayoutArea && <OffLayoutArea />}
</div>
);
};
const { getByText } = renderWithRefineContext(
<LayoutWrapper>
<div>test </div>
</LayoutWrapper>,
{
hasDashboard: false,
Layout: CustomLayout,
Sider: CustomSider,
Header: CustomHeader,
Footer: CustomFooter,
OffLayoutArea: CustomOffLayoutArea,
Title: CustomTitle,
...defaultRefineOptions,
options: defaultRefineOptions,
},
);
getByText(customSiderContent);
getByText(customHeaderContent);
getByText(customFooterContent);
getByText(customOffLayoutAreaContent);
getByText(customTitleContent);
});
it("By default, LayoutWrapper not renders the custom components", () => {
const customSiderContent = "customSiderContent";
const CustomSider = () => <p>{customSiderContent}</p>;
const customHeaderContent = "customHeaderContent";
const CustomHeader = () => <p>{customHeaderContent}</p>;
const customFooterContent = "customFooterContent";
const CustomFooter = () => <p>{customFooterContent}</p>;
const customOffLayoutAreaContent = "customOffLayoutAreaContent";
const CustomOffLayoutArea = () => <p>{customOffLayoutAreaContent}</p>;
const customTitleContent = "customTitleContent";
const CustomTitle = () => <p>{customTitleContent}</p>;
const { queryByText } = renderWithRefineContext(
<LayoutWrapper>
<div>test </div>
</LayoutWrapper>,
{
hasDashboard: false,
Sider: CustomSider,
Header: CustomHeader,
Footer: CustomFooter,
OffLayoutArea: CustomOffLayoutArea,
Title: CustomTitle,
...defaultRefineOptions,
options: defaultRefineOptions,
},
);
expect(queryByText(customSiderContent)).toBeNull();
expect(queryByText(customHeaderContent)).toBeNull();
expect(queryByText(customFooterContent)).toBeNull();
expect(queryByText(customOffLayoutAreaContent)).toBeNull();
expect(queryByText(customTitleContent)).toBeNull();
});
it("LayoutWrapper renders custom layout, sider, header, footer, title, offLayoutArea if given props", () => {
const customTitleContent = "customTitleContent";
const CustomTitle = () => <p>{customTitleContent}</p>;
const CustomLayout: React.FC<LayoutProps> = ({
Header,
Sider,
Footer,
OffLayoutArea,
children,
}) => (
<div>
{Header && <Header />}
{Sider && <Sider />}
{children}
<div>custom layout</div>
{Footer && <Footer />}
{OffLayoutArea && <OffLayoutArea />}
</div>
);
const customSiderContent = "customSiderContent";
const CustomSider = () => <p>{customSiderContent}</p>;
const customHeaderContent = "customHeaderContent";
const CustomHeader = () => <p>{customHeaderContent}</p>;
const customFooterContent = "customFooterContent";
const CustomFooter = () => <p>{customFooterContent}</p>;
const customOffLayoutAreaContent = "customOffLayoutAreaContent";
const CustomOffLayoutArea = () => <p>{customOffLayoutAreaContent}</p>;
const { getByText } = renderWithRefineContext(
<LayoutWrapper
Layout={CustomLayout}
Title={CustomTitle}
Sider={CustomSider}
Header={CustomHeader}
Footer={CustomFooter}
OffLayoutArea={CustomOffLayoutArea}
>
<div>test</div>
</LayoutWrapper>,
{
...defaultRefineOptions,
options: defaultRefineOptions,
hasDashboard: false,
},
);
expect(getByText(customSiderContent));
expect(getByText(customHeaderContent));
expect(getByText(customFooterContent));
expect(getByText(customOffLayoutAreaContent));
expect(getByText("custom layout"));
});
});

View File

@@ -0,0 +1,121 @@
import React, { useEffect } from "react";
import {
useRefineContext,
useRouterContext,
useTranslate,
useWarnAboutChange,
} from "@hooks";
import { LayoutProps, TitleProps } from "../../interfaces";
export interface LayoutWrapperProps {
/**
* Outer component that renders other components
* @default *
*/
Layout?: React.FC<LayoutProps>;
/**
* [Custom sider to use](/api-reference/core/components/refine-config.md#sider)
* @default *
*/
Sider?: React.FC;
/**
* [Custom header to use](/api-reference/core/components/refine-config.md#header)
* @default *
*/
Header?: React.FC;
/**
* [Custom title to use](/api-reference/core/components/refine-config.md#title)
* @default *
*/
Title?: React.FC<TitleProps>;
/**
* [Custom footer to use](/api-reference/core/components/refine-config.md#footer)
* @default *
*/
Footer?: React.FC;
/**
* [Custom off layout area to use](/api-reference/core/components/refine-config.md#offlayoutarea)
* @default *
*/
OffLayoutArea?: React.FC;
children: React.ReactNode;
}
/**
* `<LayoutWrapper>` wraps its contents in **refine's** layout with all customizations made in {@link https://refine.dev/docs/core/components/refine-config `<Refine>`} component.
* It is the default layout used in resource pages.
* It can be used in custom pages to use global layout.
*
* @see {@link https://refine.dev/docs/core/components/layout-wrapper} for more details.
*
* @deprecated This component is obsolete and only works with the legacy router providers.
*/
export const LayoutWrapper: React.FC<LayoutWrapperProps> = ({
children,
Layout: LayoutFromProps,
Sider: SiderFromProps,
Header: HeaderFromProps,
Title: TitleFromProps,
Footer: FooterFromProps,
OffLayoutArea: OffLayoutAreaFromProps,
}) => {
const { Layout, Footer, Header, Sider, Title, OffLayoutArea } =
useRefineContext();
const LayoutToRender = LayoutFromProps ?? Layout;
return (
<LayoutToRender
Sider={SiderFromProps ?? Sider}
Header={HeaderFromProps ?? Header}
Footer={FooterFromProps ?? Footer}
Title={TitleFromProps ?? Title}
OffLayoutArea={OffLayoutAreaFromProps ?? OffLayoutArea}
>
{children}
<UnsavedPrompt />
</LayoutToRender>
);
};
const UnsavedPrompt: React.FC = () => {
const { Prompt } = useRouterContext();
const translate = useTranslate();
const { warnWhen, setWarnWhen } = useWarnAboutChange();
const warnWhenListener = (e: {
preventDefault: () => void;
returnValue: string;
}) => {
e.preventDefault();
e.returnValue = translate(
"warnWhenUnsavedChanges",
"Are you sure you want to leave? You have unsaved changes.",
);
return e.returnValue;
};
useEffect(() => {
if (warnWhen) {
window.addEventListener("beforeunload", warnWhenListener);
}
return window.removeEventListener("beforeunload", warnWhenListener);
}, [warnWhen]);
return (
<Prompt
when={warnWhen}
message={translate(
"warnWhenUnsavedChanges",
"Are you sure you want to leave? You have unsaved changes.",
)}
setWarnWhen={setWarnWhen}
/>
);
};