@etsoo/toolpad 1.0.9 → 1.0.11

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.
@@ -60,7 +60,4 @@ export interface AccountProps {
60
60
  * - [Account API](https://mui.com/toolpad/core/api/account)
61
61
  */
62
62
  declare function Account(props: AccountProps): import("react/jsx-runtime").JSX.Element | null;
63
- declare namespace Account {
64
- var propTypes: any;
65
- }
66
63
  export { Account };
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
- import PropTypes from "prop-types";
4
3
  import Popover from "@mui/material/Popover";
5
4
  import Divider from "@mui/material/Divider";
6
5
  import Stack from "@mui/material/Stack";
@@ -64,44 +63,4 @@ function Account(props) {
64
63
  ...slotProps?.popover?.slotProps
65
64
  }, children: slots?.popoverContent ? (_jsx(slots.popoverContent, { ...slotProps?.popoverContent })) : (_jsxs(Stack, { direction: "column", ...slotProps?.popoverContent, children: [_jsx(AccountPopoverHeader, { children: _jsx(AccountPreview, { variant: "expanded" }) }), _jsx(Divider, {}), _jsx(AccountPopoverFooter, { children: _jsx(SignOutButton, { ...slotProps?.signOutButton }) })] })) }))] }));
66
65
  }
67
- Account.propTypes /* remove-proptypes */ = {
68
- // ┌────────────────────────────── Warning ──────────────────────────────┐
69
- // │ These PropTypes are generated from the TypeScript type definitions. │
70
- // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
71
- // └─────────────────────────────────────────────────────────────────────┘
72
- /**
73
- * The props used for each slot inside.
74
- */
75
- slotProps: PropTypes.shape({
76
- popover: PropTypes.object,
77
- popoverContent: PropTypes.object,
78
- preview: PropTypes.shape({
79
- handleClick: PropTypes.func,
80
- open: PropTypes.bool,
81
- slotProps: PropTypes.shape({
82
- avatar: PropTypes.object,
83
- avatarIconButton: PropTypes.object,
84
- moreIconButton: PropTypes.object
85
- }),
86
- slots: PropTypes.shape({
87
- avatar: PropTypes.elementType,
88
- avatarIconButton: PropTypes.elementType,
89
- moreIconButton: PropTypes.elementType
90
- }),
91
- variant: PropTypes.oneOf(["condensed", "expanded"])
92
- }),
93
- signInButton: PropTypes.object,
94
- signOutButton: PropTypes.object
95
- }),
96
- /**
97
- * The components used for each slot inside.
98
- */
99
- slots: PropTypes.shape({
100
- popover: PropTypes.elementType,
101
- popoverContent: PropTypes.elementType,
102
- preview: PropTypes.elementType,
103
- signInButton: PropTypes.elementType,
104
- signOutButton: PropTypes.elementType
105
- })
106
- };
107
66
  export { Account };
@@ -61,7 +61,4 @@ export interface AccountPreviewProps {
61
61
  * - [AccountPreview API](https://mui.com/toolpad/core/api/account-preview)
62
62
  */
63
63
  declare function AccountPreview(props: AccountPreviewProps): import("react/jsx-runtime").JSX.Element | null;
64
- declare namespace AccountPreview {
65
- var propTypes: any;
66
- }
67
64
  export { AccountPreview };
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
- import PropTypes from "prop-types";
4
3
  import Avatar from "@mui/material/Avatar";
5
4
  import Typography from "@mui/material/Typography";
6
5
  import Tooltip from "@mui/material/Tooltip";
@@ -56,40 +55,4 @@ function AccountPreview(props) {
56
55
  }
57
56
  return (_jsx(Tooltip, { title: session.user.name ?? "Account", children: slots?.avatarIconButton ? (_jsx(slots.avatarIconButton, {})) : (_jsx(IconButton, { onClick: handleClick, "aria-label": localeText.accountIconButtonAriaLabel, size: "small", "aria-controls": open ? "account-menu" : undefined, "aria-haspopup": "true", "aria-expanded": open ? "true" : undefined, ...slotProps?.avatarIconButton, children: avatarContent })) }));
58
57
  }
59
- AccountPreview.propTypes /* remove-proptypes */ = {
60
- // ┌────────────────────────────── Warning ──────────────────────────────┐
61
- // │ These PropTypes are generated from the TypeScript type definitions. │
62
- // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
63
- // └─────────────────────────────────────────────────────────────────────┘
64
- /**
65
- * The handler used when the preview is expanded
66
- */
67
- handleClick: PropTypes.func,
68
- /**
69
- * The state of the Account popover
70
- * @default false
71
- */
72
- open: PropTypes.bool,
73
- /**
74
- * The props used for each slot inside.
75
- */
76
- slotProps: PropTypes.shape({
77
- avatar: PropTypes.object,
78
- avatarIconButton: PropTypes.object,
79
- moreIconButton: PropTypes.object
80
- }),
81
- /**
82
- * The components used for each slot inside.
83
- */
84
- slots: PropTypes.shape({
85
- avatar: PropTypes.elementType
86
- }),
87
- /**
88
- * The type of account details to display.
89
- * @property {'condensed'} condensed - Shows only the user's avatar.
90
- * @property {'expanded'} expanded - Displays the user's avatar, name, and email if available.
91
- * @default 'condensed'
92
- */
93
- variant: PropTypes.oneOf(["condensed", "expanded"])
94
- };
95
58
  export { AccountPreview };
@@ -16,7 +16,7 @@ export interface Router {
16
16
  navigate: Navigate;
17
17
  }
18
18
  export interface Branding {
19
- title?: string | React.ReactNode | [string, (handler: React.MouseEvent<HTMLSpanElement>) => void];
19
+ title?: React.ReactNode | [string, (handler: React.MouseEvent<HTMLSpanElement>) => void];
20
20
  logo?: React.ReactNode;
21
21
  }
22
22
  export interface NavigationPageItem {
@@ -27,6 +27,7 @@ export interface NavigationPageItem {
27
27
  pattern?: string;
28
28
  action?: React.ReactNode;
29
29
  children?: Navigation;
30
+ subs?: string[];
30
31
  }
31
32
  export interface NavigationSubheaderItem {
32
33
  kind: "header";
@@ -11,7 +11,4 @@ import { AppProviderProps } from "./AppProvider";
11
11
  * - [AppProvider API](https://mui.com/toolpad/core/api/app-provider)
12
12
  */
13
13
  declare function AppProvider(props: AppProviderProps): import("react/jsx-runtime").JSX.Element;
14
- declare namespace AppProvider {
15
- var propTypes: any;
16
- }
17
14
  export { AppProvider };
@@ -1,6 +1,5 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import PropTypes from "prop-types";
4
3
  import { BrandingContext, NavigationContext, RouterContext, WindowContext } from "../shared/context";
5
4
  import { AppThemeProvider } from "./AppThemeProvider";
6
5
  import { createTheme as createMuiTheme } from "@mui/material/styles";
@@ -29,93 +28,4 @@ function AppProvider(props) {
29
28
  const { children, theme = createTheme(), branding = null, localeText, navigation = [], router = null, authentication = null, session = null, window: appWindow } = props;
30
29
  return (_jsx(WindowContext.Provider, { value: appWindow, children: _jsx(AuthenticationContext.Provider, { value: authentication, children: _jsx(SessionContext.Provider, { value: session, children: _jsx(RouterContext.Provider, { value: router, children: _jsx(AppThemeProvider, { theme: theme, window: appWindow, children: _jsx(LocaleProvider, { localeText: localeText, children: _jsx(BrandingContext.Provider, { value: branding, children: _jsx(NavigationContext.Provider, { value: navigation, children: children }) }) }) }) }) }) }) }));
31
30
  }
32
- AppProvider.propTypes /* remove-proptypes */ = {
33
- // ┌────────────────────────────── Warning ──────────────────────────────┐
34
- // │ These PropTypes are generated from the TypeScript type definitions. │
35
- // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
36
- // └─────────────────────────────────────────────────────────────────────┘
37
- /**
38
- * Authentication methods.
39
- * @default null
40
- */
41
- authentication: PropTypes.shape({
42
- signIn: PropTypes.func.isRequired,
43
- signOut: PropTypes.func.isRequired
44
- }),
45
- /**
46
- * Branding options for the app.
47
- * @default null
48
- */
49
- branding: PropTypes.shape({
50
- logo: PropTypes.node,
51
- title: PropTypes.node
52
- }),
53
- /**
54
- * The content of the app provider.
55
- */
56
- children: PropTypes.node,
57
- /**
58
- * Navigation definition for the app.
59
- * @default []
60
- */
61
- navigation: PropTypes.arrayOf(PropTypes.oneOfType([
62
- PropTypes.shape({
63
- action: PropTypes.node,
64
- children: PropTypes.arrayOf(PropTypes.oneOfType([
65
- PropTypes.object,
66
- PropTypes.shape({
67
- kind: PropTypes.oneOf(["header"]).isRequired,
68
- title: PropTypes.string.isRequired
69
- }),
70
- PropTypes.shape({
71
- kind: PropTypes.oneOf(["divider"]).isRequired
72
- })
73
- ]).isRequired),
74
- icon: PropTypes.node,
75
- kind: PropTypes.oneOf(["page"]),
76
- pattern: PropTypes.string,
77
- segment: PropTypes.string,
78
- title: PropTypes.string
79
- }),
80
- PropTypes.shape({
81
- kind: PropTypes.oneOf(["header"]).isRequired,
82
- title: PropTypes.string.isRequired
83
- }),
84
- PropTypes.shape({
85
- kind: PropTypes.oneOf(["divider"]).isRequired
86
- })
87
- ]).isRequired),
88
- /**
89
- * Router implementation used inside Toolpad components.
90
- * @default null
91
- */
92
- router: PropTypes.shape({
93
- navigate: PropTypes.func.isRequired,
94
- pathname: PropTypes.string.isRequired,
95
- searchParams: PropTypes.instanceOf(URLSearchParams).isRequired
96
- }),
97
- /**
98
- * Session info about the current user.
99
- * @default null
100
- */
101
- session: PropTypes.shape({
102
- user: PropTypes.shape({
103
- email: PropTypes.string,
104
- id: PropTypes.string,
105
- image: PropTypes.string,
106
- name: PropTypes.string
107
- })
108
- }),
109
- /**
110
- * [Theme or themes](https://mui.com/toolpad/core/react-app-provider/#theming) to be used by the app in light/dark mode. A [CSS variables theme](https://mui.com/material-ui/customization/css-theme-variables/overview/) is recommended.
111
- * @default createTheme()
112
- */
113
- theme: PropTypes.object,
114
- /**
115
- * The window where the application is rendered.
116
- * This is needed when rendering the app inside an iframe, for example.
117
- * @default window
118
- */
119
- window: PropTypes.object
120
- };
121
31
  export { AppProvider };
@@ -88,7 +88,4 @@ export interface DashboardLayoutProps {
88
88
  * - [DashboardLayout API](https://mui.com/toolpad/core/api/dashboard-layout)
89
89
  */
90
90
  declare function DashboardLayout(props: DashboardLayoutProps): import("react/jsx-runtime").JSX.Element;
91
- declare namespace DashboardLayout {
92
- var propTypes: any;
93
- }
94
91
  export { DashboardLayout };
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import PropTypes from "prop-types";
5
4
  import { styled, useTheme } from "@mui/material";
6
5
  import MuiAppBar from "@mui/material/AppBar";
7
6
  import Box from "@mui/material/Box";
@@ -191,85 +190,4 @@ function DashboardLayout(props) {
191
190
  overflow: "auto"
192
191
  }, children: children })] })] }));
193
192
  }
194
- DashboardLayout.propTypes /* remove-proptypes */ = {
195
- // ┌────────────────────────────── Warning ──────────────────────────────┐
196
- // │ These PropTypes are generated from the TypeScript type definitions. │
197
- // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
198
- // └─────────────────────────────────────────────────────────────────────┘
199
- /**
200
- * The content of the dashboard.
201
- */
202
- children: PropTypes.node,
203
- /**
204
- * Whether the sidebar should start collapsed in desktop size screens.
205
- * @default false
206
- */
207
- defaultSidebarCollapsed: PropTypes.bool,
208
- /**
209
- * Whether the sidebar should not be collapsible to a mini variant in desktop and tablet viewports.
210
- * @default false
211
- */
212
- disableCollapsibleSidebar: PropTypes.bool,
213
- /**
214
- * Whether the navigation bar and menu icon should be hidden
215
- * @default false
216
- */
217
- hideNavigation: PropTypes.bool,
218
- /**
219
- * Width of the sidebar when expanded.
220
- * @default 320
221
- */
222
- sidebarExpandedWidth: PropTypes.oneOfType([
223
- PropTypes.number,
224
- PropTypes.string
225
- ]),
226
- /**
227
- * The props used for each slot inside.
228
- * @default {}
229
- */
230
- slotProps: PropTypes.shape({
231
- sidebarFooter: PropTypes.shape({
232
- mini: PropTypes.bool.isRequired
233
- }),
234
- toolbarAccount: PropTypes.shape({
235
- localeText: PropTypes.shape({
236
- iconButtonAriaLabel: PropTypes.string,
237
- signInLabel: PropTypes.string,
238
- signOutLabel: PropTypes.string
239
- }),
240
- slotProps: PropTypes.shape({
241
- popover: PropTypes.object,
242
- popoverContent: PropTypes.object,
243
- preview: PropTypes.object,
244
- signInButton: PropTypes.object,
245
- signOutButton: PropTypes.object
246
- }),
247
- slots: PropTypes.shape({
248
- popover: PropTypes.elementType,
249
- popoverContent: PropTypes.elementType,
250
- preview: PropTypes.elementType,
251
- signInButton: PropTypes.elementType,
252
- signOutButton: PropTypes.elementType
253
- })
254
- }),
255
- toolbarActions: PropTypes.object
256
- }),
257
- /**
258
- * The components used for each slot inside.
259
- * @default {}
260
- */
261
- slots: PropTypes.shape({
262
- sidebarFooter: PropTypes.elementType,
263
- toolbarAccount: PropTypes.elementType,
264
- toolbarActions: PropTypes.elementType
265
- }),
266
- /**
267
- * The system prop that allows defining system overrides as well as additional CSS styles.
268
- */
269
- sx: PropTypes.oneOfType([
270
- PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])),
271
- PropTypes.func,
272
- PropTypes.object
273
- ])
274
- };
275
193
  export { DashboardLayout };
@@ -97,12 +97,10 @@ function DashboardSidebarSubNavigation({ subNavigation, basePath = "", depth = 0
97
97
  const isNestedNavigationExpanded = expandedSidebarItemIds.includes(navigationItemId);
98
98
  const nestedNavigationCollapseIcon = isNestedNavigationExpanded ? (_jsx(ExpandLessIcon, {})) : (_jsx(ExpandMoreIcon, {}));
99
99
  const listItemIconSize = 34;
100
- const isSelected = isPageItemSelected(navigationItem, basePath, pathname);
101
- if (process.env.NODE_ENV !== "production" &&
102
- isSelected &&
103
- selectedItemId) {
104
- console.warn(`Duplicate selected path in navigation: ${navigationItemFullPath}`);
105
- }
100
+ // If the item is selected, we don't want to select more
101
+ const isSelected = selectedItemId
102
+ ? false
103
+ : isPageItemSelected(navigationItem, basePath, pathname);
106
104
  if (isSelected && !selectedItemId) {
107
105
  selectedItemId = navigationItemId;
108
106
  }
@@ -42,7 +42,10 @@ export function TitleBar() {
42
42
  }
43
43
  return [title, false];
44
44
  }, [title]);
45
- if (!hasLink)
45
+ if (hasLink) {
46
+ return (_jsx(Link, { href: "/", style: { color: "inherit", textDecoration: "none" }, children: _jsxs(Stack, { direction: "row", alignItems: "center", children: [branding?.logo && _jsx(LogoContainer, { children: branding.logo }), titleUI] }) }));
47
+ }
48
+ else {
46
49
  return titleUI;
47
- return (_jsx(Link, { href: "/", style: { color: "inherit", textDecoration: "none" }, children: _jsxs(Stack, { direction: "row", alignItems: "center", children: [branding?.logo && _jsx(LogoContainer, { children: branding.logo }), titleUI] }) }));
50
+ }
48
51
  }
@@ -21,20 +21,18 @@ export interface Breadcrumb {
21
21
  */
22
22
  path: string;
23
23
  }
24
- /**
25
- * @deprecated Use `Breadcrumb` instead.
26
- */
27
- export type BreadCrumb = Breadcrumb;
28
- export interface PageContainerProps extends ContainerProps {
29
- children?: React.ReactNode;
30
- /**
31
- * The title of the page. Leave blank to use the active page title.
32
- */
24
+ export type PageData = {
33
25
  title?: string;
34
- /**
35
- * The breadcrumbs of the page. Leave blank to use the active page breadcrumbs.
36
- */
26
+ page?: string;
37
27
  breadcrumbs?: Breadcrumb[];
28
+ };
29
+ type PageDataAction = PageData | true;
30
+ export declare const PageDataContext: React.Context<{
31
+ state: PageData;
32
+ dispatch: React.Dispatch<PageDataAction>;
33
+ }>;
34
+ export declare function PageDataContextProvider(props: React.PropsWithChildren<PageData>): import("react/jsx-runtime").JSX.Element;
35
+ export type PageContainerProps = React.PropsWithChildren<ContainerProps & {
38
36
  /**
39
37
  * The components used for each slot inside.
40
38
  */
@@ -43,7 +41,7 @@ export interface PageContainerProps extends ContainerProps {
43
41
  * The props used for each slot inside.
44
42
  */
45
43
  slotProps?: PageContainerSlotProps;
46
- }
44
+ }>;
47
45
  /**
48
46
  * A container component to provide a title and breadcrumbs for your pages.
49
47
  *
@@ -56,7 +54,4 @@ export interface PageContainerProps extends ContainerProps {
56
54
  * - [PageContainer API](https://mui.com/toolpad/core/api/page-container)
57
55
  */
58
56
  declare function PageContainer(props: PageContainerProps): import("react/jsx-runtime").JSX.Element;
59
- declare namespace PageContainer {
60
- var propTypes: any;
61
- }
62
57
  export { PageContainer };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import PropTypes from "prop-types";
3
+ import * as React from "react";
4
4
  import Breadcrumbs from "@mui/material/Breadcrumbs";
5
5
  import Container from "@mui/material/Container";
6
6
  import Link from "@mui/material/Link";
@@ -18,6 +18,29 @@ const PageContentHeader = styled("div")(({ theme }) => ({
18
18
  justifyContent: "space-between",
19
19
  gap: theme.spacing(2)
20
20
  }));
21
+ export const PageDataContext = React.createContext({ state: {}, dispatch: (value) => value });
22
+ function reducer(state, action) {
23
+ if (action === true) {
24
+ // Reset the state
25
+ if (state.breadcrumbs == null &&
26
+ state.title == null &&
27
+ state.page == null) {
28
+ return state;
29
+ }
30
+ else {
31
+ return {};
32
+ }
33
+ }
34
+ return { ...state, ...action };
35
+ }
36
+ export function PageDataContextProvider(props) {
37
+ // Destruct
38
+ const { title, breadcrumbs, ...rest } = props;
39
+ // useReducer hook to manage state with our reducer function and initial state
40
+ const [state, dispatch] = React.useReducer(reducer, { title, breadcrumbs });
41
+ // Provide the state and dispatch function to the context value
42
+ return _jsx(PageDataContext.Provider, { value: { state, dispatch }, ...rest });
43
+ }
21
44
  /**
22
45
  * A container component to provide a title and breadcrumbs for your pages.
23
46
  *
@@ -30,11 +53,26 @@ const PageContentHeader = styled("div")(({ theme }) => ({
30
53
  * - [PageContainer API](https://mui.com/toolpad/core/api/page-container)
31
54
  */
32
55
  function PageContainer(props) {
33
- const { children, slots, slotProps, breadcrumbs, ...rest } = props;
56
+ const { children, slots, slotProps, ...rest } = props;
57
+ const loaded = React.useRef(false);
58
+ const { state, dispatch } = React.useContext(PageDataContext);
34
59
  const activePage = useActivePage();
35
- // TODO: Remove `props.breadCrumbs` in the next major version
36
- const resolvedBreadcrumbs = breadcrumbs ?? activePage?.breadcrumbs ?? [];
37
- const title = props.title ?? activePage?.title ?? "";
60
+ React.useLayoutEffect(() => {
61
+ if (loaded.current) {
62
+ dispatch(true);
63
+ }
64
+ else {
65
+ loaded.current = true;
66
+ }
67
+ }, [activePage?.sourcePath]);
68
+ let resolvedBreadcrumbs = state.breadcrumbs ?? activePage?.breadcrumbs ?? [];
69
+ const title = state.title ?? activePage?.title ?? "";
70
+ if (state.page) {
71
+ resolvedBreadcrumbs = [
72
+ ...resolvedBreadcrumbs,
73
+ { title: state.page, path: "#" }
74
+ ];
75
+ }
38
76
  const ToolbarComponent = props?.slots?.toolbar ?? PageContainerToolbar;
39
77
  const toolbarSlotProps = useSlotProps({
40
78
  elementType: ToolbarComponent,
@@ -48,39 +86,4 @@ function PageContainer(props) {
48
86
  })
49
87
  : null }), _jsxs(PageContentHeader, { children: [title ? _jsx(Typography, { variant: "h4", children: title }) : null, _jsx(ToolbarComponent, { ...toolbarSlotProps })] })] }), _jsx("div", { children: children })] }) }));
50
88
  }
51
- PageContainer.propTypes /* remove-proptypes */ = {
52
- // ┌────────────────────────────── Warning ──────────────────────────────┐
53
- // │ These PropTypes are generated from the TypeScript type definitions. │
54
- // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
55
- // └─────────────────────────────────────────────────────────────────────┘
56
- /**
57
- * The breadcrumbs of the page. Leave blank to use the active page breadcrumbs.
58
- */
59
- breadcrumbs: PropTypes.arrayOf(PropTypes.shape({
60
- path: PropTypes.string.isRequired,
61
- title: PropTypes.string.isRequired
62
- })),
63
- /**
64
- * @ignore
65
- */
66
- children: PropTypes.node,
67
- /**
68
- * The props used for each slot inside.
69
- */
70
- slotProps: PropTypes.shape({
71
- toolbar: PropTypes.shape({
72
- children: PropTypes.node
73
- }).isRequired
74
- }),
75
- /**
76
- * The components used for each slot inside.
77
- */
78
- slots: PropTypes.shape({
79
- toolbar: PropTypes.elementType
80
- }),
81
- /**
82
- * The title of the page. Leave blank to use the active page title.
83
- */
84
- title: PropTypes.string
85
- };
86
89
  export { PageContainer };
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { expect, describe, test, vi } from "vitest";
3
- import { render, within, screen } from "@testing-library/react";
3
+ import { render, within, screen, act } from "@testing-library/react";
4
4
  import { userEvent } from "@testing-library/user-event";
5
- import { PageContainer } from "./PageContainer";
5
+ import { PageContainer, PageDataContextProvider } from "./PageContainer";
6
6
  import describeConformance from "../utils/describeConformance";
7
7
  import { AppProvider } from "../AppProvider/AppProviderComponent";
8
8
  describe("PageContainer", () => {
@@ -13,16 +13,18 @@ describe("PageContainer", () => {
13
13
  }
14
14
  }));
15
15
  test("renders page container correctly", async () => {
16
- const user = await userEvent.setup();
16
+ const user = userEvent.setup();
17
17
  const router = {
18
18
  pathname: "/orders",
19
19
  searchParams: new URLSearchParams(),
20
20
  navigate: vi.fn()
21
21
  };
22
- render(_jsx(AppProvider, { navigation: [
23
- { segment: "", title: "Home" },
24
- { segment: "orders", title: "Orders" }
25
- ], router: router, children: _jsx(PageContainer, {}) }));
22
+ act(() => {
23
+ render(_jsx(AppProvider, { navigation: [
24
+ { segment: "", title: "Home" },
25
+ { segment: "orders", title: "Orders" }
26
+ ], router: router, children: _jsx(PageDataContextProvider, { children: _jsx(PageContainer, {}) }) }));
27
+ });
26
28
  const breadcrumbs = screen.getByRole("navigation", { name: "breadcrumb" });
27
29
  const homeLink = within(breadcrumbs).getByRole("link", { name: "Home" });
28
30
  await user.click(homeLink);
@@ -51,23 +53,27 @@ describe("PageContainer", () => {
51
53
  navigate: vi.fn()
52
54
  };
53
55
  const branding = { title: "ACME" };
54
- render(_jsx(AppProvider, { branding: branding, navigation: navigation, router: router, children: _jsx(PageContainer, {}) }));
56
+ act(() => {
57
+ render(_jsx(AppProvider, { branding: branding, navigation: navigation, router: router, children: _jsx(PageDataContextProvider, { children: _jsx(PageContainer, {}) }) }));
58
+ });
55
59
  const breadcrumbs = screen.getByRole("navigation", { name: "breadcrumb" });
56
60
  expect(within(breadcrumbs).getByText("ACME")).toBeTruthy();
57
61
  expect(within(breadcrumbs).getByText("Home")).toBeTruthy();
58
62
  expect(within(breadcrumbs).getByText("Orders")).toBeTruthy();
59
63
  });
60
64
  test("renders dynamic correctly", async () => {
61
- const user = await userEvent.setup();
65
+ const user = userEvent.setup();
62
66
  const router = {
63
67
  pathname: "/orders/123",
64
68
  searchParams: new URLSearchParams(),
65
69
  navigate: vi.fn()
66
70
  };
67
- render(_jsx(AppProvider, { navigation: [
68
- { segment: "", title: "Home" },
69
- { segment: "orders", title: "Orders", pattern: "orders/:id" }
70
- ], router: router, children: _jsx(PageContainer, {}) }));
71
+ act(() => {
72
+ render(_jsx(AppProvider, { navigation: [
73
+ { segment: "", title: "Home" },
74
+ { segment: "orders", title: "Orders", pattern: "orders/:id" }
75
+ ], router: router, children: _jsx(PageDataContextProvider, { children: _jsx(PageContainer, {}) }) }));
76
+ });
71
77
  const breadcrumbs = screen.getByRole("navigation", { name: "breadcrumb" });
72
78
  const homeLink = within(breadcrumbs).getByRole("link", { name: "Home" });
73
79
  await user.click(homeLink);
@@ -82,29 +88,33 @@ describe("PageContainer", () => {
82
88
  searchParams: new URLSearchParams(),
83
89
  navigate: vi.fn()
84
90
  };
85
- render(_jsx(AppProvider, { navigation: [
86
- {
87
- segment: "users",
88
- title: "Users",
89
- children: [
90
- {
91
- segment: "invoices",
92
- title: "Invoices",
93
- pattern: "invoices/:id"
94
- }
95
- ]
96
- }
97
- ], router: router, children: _jsx(PageContainer, {}) }));
91
+ act(() => {
92
+ render(_jsx(AppProvider, { navigation: [
93
+ {
94
+ segment: "users",
95
+ title: "Users",
96
+ children: [
97
+ {
98
+ segment: "invoices",
99
+ title: "Invoices",
100
+ pattern: "invoices/:id"
101
+ }
102
+ ]
103
+ }
104
+ ], router: router, children: _jsx(PageDataContextProvider, { children: _jsx(PageContainer, {}) }) }));
105
+ });
98
106
  const breadcrumbs = screen.getByRole("navigation", { name: "breadcrumb" });
99
107
  const homeLink = within(breadcrumbs).getByRole("link", { name: "Users" });
100
108
  expect(homeLink.getAttribute("href")).toBe("/users");
101
109
  expect(within(breadcrumbs).getByText("Invoices")).toBeTruthy();
102
110
  });
103
111
  test("renders custom breadcrumbs", async () => {
104
- render(_jsx(PageContainer, { breadcrumbs: [
105
- { title: "Hello", path: "/hello" },
106
- { title: "World", path: "/world" }
107
- ] }));
112
+ act(() => {
113
+ render(_jsx(PageDataContextProvider, { breadcrumbs: [
114
+ { title: "Hello", path: "/hello" },
115
+ { title: "World", path: "/world" }
116
+ ], children: _jsx(PageContainer, {}) }));
117
+ });
108
118
  const breadcrumbs = screen.getByRole("navigation", { name: "breadcrumb" });
109
119
  const helloLink = within(breadcrumbs).getByRole("link", { name: "Hello" });
110
120
  expect(helloLink.getAttribute("href")).toBe("/hello");