diff --git a/docs/data/toolpad/core/components/page-container/CustomPageContainer.js b/docs/data/toolpad/core/components/page-container/CustomPageContainer.js new file mode 100644 index 00000000000..a792a7df846 --- /dev/null +++ b/docs/data/toolpad/core/components/page-container/CustomPageContainer.js @@ -0,0 +1,71 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { PageContainer } from '@toolpad/core/PageContainer'; +import { AppProvider } from '@toolpad/core/AppProvider'; +import { Link, useDemoRouter } from '@toolpad/core/internals'; +import { useActivePage } from '@toolpad/core/useActivePage'; +import { useTheme } from '@mui/material/styles'; +import Box from '@mui/material/Box'; +import Paper from '@mui/material/Paper'; +import invariant from 'invariant'; + +const NAVIGATION = [ + { + segment: 'inbox', + title: 'Orders', + pattern: '/inbox/:id', + }, +]; + +function Content({ router }) { + const id = Number(router.pathname.replace('/inbox/', '')); + + const activePage = useActivePage(); + invariant(activePage, 'No navigation match'); + + const title = `Item ${id}`; + const path = `${activePage.path}/${id}`; + + const breadCrumbs = [...activePage.breadCrumbs, { title, path }]; + + return ( + // preview-start + + {/* preview-end */} + + previous + next + + + ); +} + +Content.propTypes = { + router: PropTypes.shape({ + navigate: PropTypes.func.isRequired, + pathname: PropTypes.string.isRequired, + searchParams: PropTypes.instanceOf(URLSearchParams).isRequired, + }).isRequired, +}; + +export default function CustomPageContainer() { + const router = useDemoRouter('/inbox/123'); + + const theme = useTheme(); + + let content = ( + + Item 123 + + ); + + if (router.pathname.startsWith('/inbox/')) { + content = ; + } + + return ( + + {content} + + ); +} diff --git a/docs/data/toolpad/core/components/page-container/CustomPageContainer.tsx b/docs/data/toolpad/core/components/page-container/CustomPageContainer.tsx new file mode 100644 index 00000000000..3b913515a49 --- /dev/null +++ b/docs/data/toolpad/core/components/page-container/CustomPageContainer.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import { PageContainer } from '@toolpad/core/PageContainer'; +import { AppProvider, Router } from '@toolpad/core/AppProvider'; +import { Link, useDemoRouter } from '@toolpad/core/internals'; +import { useActivePage } from '@toolpad/core/useActivePage'; +import { useTheme } from '@mui/material/styles'; +import Box from '@mui/material/Box'; +import Paper from '@mui/material/Paper'; +import invariant from 'invariant'; + +const NAVIGATION = [ + { + segment: 'inbox', + title: 'Orders', + pattern: '/inbox/:id', + }, +]; + +interface ContentProps { + router: Router; +} + +function Content({ router }: ContentProps) { + const id = Number(router.pathname.replace('/inbox/', '')); + + const activePage = useActivePage(); + invariant(activePage, 'No navigation match'); + + const title = `Item ${id}`; + const path = `${activePage.path}/${id}`; + + const breadCrumbs = [...activePage.breadCrumbs, { title, path }]; + + return ( + // preview-start + + {/* preview-end */} + + previous + next + + + ); +} + +export default function CustomPageContainer() { + const router = useDemoRouter('/inbox/123'); + + const theme = useTheme(); + + let content = ( + + Item 123 + + ); + + if (router.pathname.startsWith('/inbox/')) { + content = ; + } + + return ( + + {content} + + ); +} diff --git a/docs/data/toolpad/core/components/page-container/CustomPageContainer.tsx.preview b/docs/data/toolpad/core/components/page-container/CustomPageContainer.tsx.preview new file mode 100644 index 00000000000..06545ed2211 --- /dev/null +++ b/docs/data/toolpad/core/components/page-container/CustomPageContainer.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.js b/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.js index a90486b361e..f0604f19386 100644 --- a/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.js +++ b/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.js @@ -6,6 +6,7 @@ import { useTheme } from '@mui/material/styles'; import Paper from '@mui/material/Paper'; const NAVIGATION = [ + { segment: '', title: 'ACME' }, { segment: 'inbox', title: 'Home', @@ -24,12 +25,7 @@ export default function TitleBreadcrumbsPageContainer() { const theme = useTheme(); return ( - + diff --git a/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.tsx b/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.tsx index a90486b361e..f0604f19386 100644 --- a/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.tsx +++ b/docs/data/toolpad/core/components/page-container/TitleBreadcrumbsPageContainer.tsx @@ -6,6 +6,7 @@ import { useTheme } from '@mui/material/styles'; import Paper from '@mui/material/Paper'; const NAVIGATION = [ + { segment: '', title: 'ACME' }, { segment: 'inbox', title: 'Home', @@ -24,12 +25,7 @@ export default function TitleBreadcrumbsPageContainer() { const theme = useTheme(); return ( - + diff --git a/docs/data/toolpad/core/components/page-container/page-container.md b/docs/data/toolpad/core/components/page-container/page-container.md index a39e4161402..81cd357c368 100644 --- a/docs/data/toolpad/core/components/page-container/page-container.md +++ b/docs/data/toolpad/core/components/page-container/page-container.md @@ -22,7 +22,6 @@ For example, under the following navigation structure: ```tsx (); + const activePage = useActivePage(); + invariant(activePage, 'No navigation match'); + + const title = `Item ${params.id}`; + const path = `${activePage.path}/${params.id}`; + + const breadCrumbs = [...activePage.breadCrumbs, { title, path }]; + + return ( + + ... + + ); +} +``` + ## Actions You can configure additional actions in the area that is reserved on the right. To do so provide the `toolbar` slot to the `PageContainer` component. You can wrap the `PageContainerToolbar` component to create a custom toolbar component, as shown here: diff --git a/docs/pages/toolpad/core/api/app-provider.json b/docs/pages/toolpad/core/api/app-provider.json index 222066ae3ea..27ff3b8a3f4 100644 --- a/docs/pages/toolpad/core/api/app-provider.json +++ b/docs/pages/toolpad/core/api/app-provider.json @@ -19,7 +19,7 @@ "router": { "type": { "name": "shape", - "description": "{ navigate: func, pathname: string, searchParams?: URLSearchParams }" + "description": "{ navigate: func, pathname: string, searchParams: URLSearchParams }" }, "default": "null" }, diff --git a/docs/pages/toolpad/core/api/page-container.json b/docs/pages/toolpad/core/api/page-container.json index 82219960b02..79293eba86a 100644 --- a/docs/pages/toolpad/core/api/page-container.json +++ b/docs/pages/toolpad/core/api/page-container.json @@ -1,5 +1,15 @@ { - "props": {}, + "props": { + "breadCrumbs": { + "type": { "name": "arrayOf", "description": "Array<{ path: string, title: string }>" } + }, + "slotProps": { "type": { "name": "shape", "description": "{ toolbar: { children?: node } }" } }, + "slots": { + "type": { "name": "shape", "description": "{ toolbar?: elementType }" }, + "additionalInfo": { "slotsApi": true } + }, + "title": { "type": { "name": "string" } } + }, "name": "PageContainer", "imports": [ "import { PageContainer } from '@toolpad/core/PageContainer';", diff --git a/docs/translations/api-docs/page-container/page-container.json b/docs/translations/api-docs/page-container/page-container.json index 643fe8e0f28..39823940d46 100644 --- a/docs/translations/api-docs/page-container/page-container.json +++ b/docs/translations/api-docs/page-container/page-container.json @@ -1,6 +1,13 @@ { - "componentDescription": "", - "propDescriptions": {}, + "componentDescription": "A container component to provide a title and breadcrumbs for your pages.", + "propDescriptions": { + "breadCrumbs": { + "description": "The breadcrumbs of the page. Leave blank to use the active page breadcrumbs." + }, + "slotProps": { "description": "The props used for each slot inside." }, + "slots": { "description": "The components used for each slot inside." }, + "title": { "description": "The title of the page. Leave blank to use the active page title." } + }, "classDescriptions": { "disableGutters": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", diff --git a/package.json b/package.json index 35a1d598f67..eabb25451d2 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@mui/internal-babel-plugin-resolve-imports": "1.0.18", "@mui/internal-docs-utils": "1.0.13", "@mui/internal-markdown": "1.0.14", - "@mui/internal-scripts": "1.0.21", + "@mui/internal-scripts": "1.0.21-dev.20240919-130050-82a6448768", "@mui/monorepo": "github:mui/material-ui#3732be30e0ae3287b55dc6a96cf1ffcfdc194906", "@mui/x-charts": "7.17.0", "@next/eslint-plugin-next": "14.2.11", diff --git a/packages/toolpad-core/src/AppProvider/AppProvider.tsx b/packages/toolpad-core/src/AppProvider/AppProvider.tsx index 029960cdadc..ba183f2bc88 100644 --- a/packages/toolpad-core/src/AppProvider/AppProvider.tsx +++ b/packages/toolpad-core/src/AppProvider/AppProvider.tsx @@ -239,10 +239,10 @@ AppProvider.propTypes /* remove-proptypes */ = { * Router implementation used inside Toolpad components. * @default null */ - router: PropTypes /* @typescript-to-proptypes-ignore */.shape({ + router: PropTypes.shape({ navigate: PropTypes.func.isRequired, pathname: PropTypes.string.isRequired, - searchParams: PropTypes.instanceOf(URLSearchParams), + searchParams: PropTypes.instanceOf(URLSearchParams).isRequired, }), /** * Session info about the current user. diff --git a/packages/toolpad-core/src/PageContainer/PageContainer.test.tsx b/packages/toolpad-core/src/PageContainer/PageContainer.test.tsx index 431cf8454dc..f6509911bd3 100644 --- a/packages/toolpad-core/src/PageContainer/PageContainer.test.tsx +++ b/packages/toolpad-core/src/PageContainer/PageContainer.test.tsx @@ -48,6 +48,7 @@ describe('PageContainer', () => { test('renders nested', async () => { const navigation = [ + { segment: '', title: 'ACME' }, { segment: 'home', title: 'Home', @@ -79,4 +80,36 @@ describe('PageContainer', () => { expect(within(breadCrumbs).getByText('Home')).toBeTruthy(); expect(within(breadCrumbs).getByText('Orders')).toBeTruthy(); }); + + test('renders dynamic correctly', async () => { + const user = await userEvent.setup(); + const router = { + pathname: '/orders/123', + searchParams: new URLSearchParams(), + navigate: vi.fn(), + }; + render( + + + , + ); + + const breadCrumbs = screen.getByRole('navigation', { name: 'breadcrumb' }); + + const homeLink = within(breadCrumbs).getByRole('link', { name: 'Home' }); + await user.click(homeLink); + + expect(router.navigate).toHaveBeenCalledWith('/', expect.objectContaining({})); + router.navigate.mockClear(); + + expect(within(breadCrumbs).getByText('Orders')).toBeTruthy(); + + expect(screen.getByText('Orders', { ignore: 'nav *' })); + }); }); diff --git a/packages/toolpad-core/src/PageContainer/PageContainer.tsx b/packages/toolpad-core/src/PageContainer/PageContainer.tsx index ba5f5052932..7ff87f6caf2 100644 --- a/packages/toolpad-core/src/PageContainer/PageContainer.tsx +++ b/packages/toolpad-core/src/PageContainer/PageContainer.tsx @@ -10,77 +10,16 @@ import useSlotProps from '@mui/utils/useSlotProps'; import { styled } from '@mui/material'; import { Link as ToolpadLink } from '../shared/Link'; import { PageContainerToolbar, PageContainerToolbarProps } from './PageContainerToolbar'; -import { NavigationContext, RouterContext } from '../shared/context'; -import { getItemTitle, isPageItem } from '../shared/navigation'; -import { NavigationItem, NavigationPageItem, Navigation } from '../AppProvider'; -import { useApplicationTitle } from '../shared/branding'; +import { getItemTitle } from '../shared/navigation'; +import { useActivePage } from '../useActivePage'; const PageContentHeader = styled('div')(({ theme }) => ({ display: 'flex', flexDirection: 'row', - jusifyCOntent: 'space-between', + jusifyContent: 'space-between', gap: theme.spacing(2), })); -const isRootPage = (item: NavigationItem) => isPageItem(item) && !item.segment; - -interface BreadCrumbItem extends NavigationPageItem { - path: string; -} - -function createPageLookup( - navigation: Navigation, - segments: BreadCrumbItem[] = [], - base = '', -): Map { - const result = new Map(); - - const resolveSegment = (segment?: string) => `${base}${segment ? `/${segment}` : ''}` || '/'; - - const root = navigation.find((item) => isRootPage(item)) as NavigationPageItem | undefined; - const rootCrumb = root ? { path: resolveSegment(''), ...root } : undefined; - - for (const item of navigation) { - if (!isPageItem(item)) { - continue; - } - - const isNonProdEnv = process.env.NODE_ENV !== 'production'; - - const path = resolveSegment(item.segment); - if (isNonProdEnv && result.has(path)) { - console.warn(`Duplicate path in navigation: ${path}`); - } - - const itemCrumb: BreadCrumbItem = { path, ...item }; - - const navigationSegments: BreadCrumbItem[] = [ - ...segments, - ...(rootCrumb && !isRootPage(item) ? [rootCrumb] : []), - itemCrumb, - ]; - - result.set(path, navigationSegments); - - if (item.children) { - const childrenLookup = createPageLookup(item.children, navigationSegments, path); - for (const [childPath, childItems] of childrenLookup) { - if (isNonProdEnv && result.has(childPath)) { - console.warn(`Duplicate path in navigation: ${childPath}`); - } - result.set(childPath, childItems); - } - } - } - - return result; -} - -function matchPath(navigation: Navigation, path: string): BreadCrumbItem[] | null { - const lookup = createPageLookup(navigation); - return lookup.get(path) ?? null; -} - export interface PageContainerSlotProps { toolbar: PageContainerToolbarProps; } @@ -93,13 +32,39 @@ export interface PageContainerSlots { toolbar: React.ElementType; } +export interface BreadCrumb { + /** + * The title of the breadcrumb segment. + */ + title: string; + /** + * The path the breadcrumb links to. + */ + path: string; +} + export interface PageContainerProps extends ContainerProps { children?: React.ReactNode; + /** + * The title of the page. Leave blank to use the active page title. + */ title?: string; + /** + * The breadcrumbs of the page. Leave blank to use the active page breadcrumbs. + */ + breadCrumbs?: BreadCrumb[]; + /** + * The components used for each slot inside. + */ slots?: PageContainerSlots; + /** + * The props used for each slot inside. + */ slotProps?: PageContainerSlotProps; } + /** + * A container component to provide a title and breadcrumbs for your pages. * * Demos: * @@ -111,28 +76,11 @@ export interface PageContainerProps extends ContainerProps { */ function PageContainer(props: PageContainerProps) { const { children, slots, slotProps, ...rest } = props; - const routerContext = React.useContext(RouterContext); - const navigationContext = React.useContext(NavigationContext); - const pathname = routerContext?.pathname ?? '/'; - const applicationTitle = useApplicationTitle(); - const breadCrumbs = React.useMemo(() => { - let crumbs = matchPath(navigationContext, pathname) ?? []; - if (crumbs.length <= 0 || crumbs[0].path !== '/') { - crumbs = [ - { - segment: '', - path: '/', - title: applicationTitle, - }, - ...crumbs, - ]; - } - return crumbs; - }, [navigationContext, pathname, applicationTitle]); + const activePage = useActivePage(); - const title = - (breadCrumbs ? getItemTitle(breadCrumbs[breadCrumbs.length - 1]) : '') ?? props.title; + const breadCrumbs = props.breadCrumbs ?? activePage?.breadCrumbs ?? []; + const title = props.title ?? activePage?.title ?? ''; const ToolbarComponent = props?.slots?.toolbar ?? PageContainerToolbar; const toolbarSlotProps = useSlotProps({ @@ -184,12 +132,21 @@ PageContainer.propTypes /* remove-proptypes */ = { // │ These PropTypes are generated from the TypeScript type definitions. │ // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ // └─────────────────────────────────────────────────────────────────────┘ + /** + * The breadcrumbs of the page. Leave blank to use the active page breadcrumbs. + */ + breadCrumbs: PropTypes.arrayOf( + PropTypes.shape({ + path: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + }), + ), /** * @ignore */ children: PropTypes.node, /** - * @ignore + * The props used for each slot inside. */ slotProps: PropTypes.shape({ toolbar: PropTypes.shape({ @@ -197,13 +154,13 @@ PageContainer.propTypes /* remove-proptypes */ = { }).isRequired, }), /** - * @ignore + * The components used for each slot inside. */ slots: PropTypes.shape({ toolbar: PropTypes.elementType, }), /** - * @ignore + * The title of the page. Leave blank to use the active page title. */ title: PropTypes.string, } as any; diff --git a/packages/toolpad-core/src/index.ts b/packages/toolpad-core/src/index.ts index c8ff0dade87..dcb98090703 100644 --- a/packages/toolpad-core/src/index.ts +++ b/packages/toolpad-core/src/index.ts @@ -8,6 +8,8 @@ export * from './Account'; export * from './PageContainer'; +export * from './useActivePage'; + export * from './useDialogs'; export * from './useNotifications'; diff --git a/packages/toolpad-core/src/internals/demo.tsx b/packages/toolpad-core/src/internals/demo.tsx index 0b41c363166..bdda55216fe 100644 --- a/packages/toolpad-core/src/internals/demo.tsx +++ b/packages/toolpad-core/src/internals/demo.tsx @@ -30,3 +30,5 @@ export function useDemoRouter(initialUrl: string = '/') { return router; } + +export { Link } from '../shared/Link'; diff --git a/packages/toolpad-core/src/shared/navigation.tsx b/packages/toolpad-core/src/shared/navigation.tsx index 851f7902af2..f986a3fd67b 100644 --- a/packages/toolpad-core/src/shared/navigation.tsx +++ b/packages/toolpad-core/src/shared/navigation.tsx @@ -1,5 +1,11 @@ import { pathToRegexp } from 'path-to-regexp'; -import type { NavigationItem, NavigationPageItem, NavigationSubheaderItem } from '../AppProvider'; +import invariant from 'invariant'; +import type { + Navigation, + NavigationItem, + NavigationPageItem, + NavigationSubheaderItem, +} from '../AppProvider'; export const getItemKind = (item: NavigationItem) => item.kind ?? 'page'; @@ -51,3 +57,110 @@ export function hasSelectedNavigationChildren( return false; } + +/** + * Builds a map of navigation page items to their respective paths. This map is used to quickly + * lookup the path of a navigation item. It will be cached for the lifetime of the navigation. + */ +function buildItemToPathMap(navigation: Navigation): Map { + const map = new Map(); + + const visit = (item: NavigationItem, base: string) => { + if (isPageItem(item)) { + const path = `${base}${item.segment ? `/${item.segment}` : ''}` || '/'; + map.set(item, path); + if (item.children) { + for (const child of item.children) { + visit(child, path); + } + } + } + }; + + for (const item of navigation) { + visit(item, ''); + } + + return map; +} + +const itemToPathMapCache = new WeakMap>(); + +/** + * Gets the cached map of navigation page items to their respective paths. + */ +function getItemToPathMap(navigation: Navigation) { + let map = itemToPathMapCache.get(navigation); + if (!map) { + map = buildItemToPathMap(navigation); + itemToPathMapCache.set(navigation, map); + } + return map; +} + +/** + * Build a lookup map of paths to navigation items. This map is used to match paths against + * to find the active page. + */ +function buildItemLookup(navigation: Navigation) { + const map = new Map(); + const visit = (item: NavigationItem) => { + if (isPageItem(item)) { + const path = getItemPath(navigation, item); + if (map.has(path)) { + console.warn(`Duplicate path in navigation: ${path}`); + } + map.set(path, item); + if (item.pattern) { + map.set(pathToRegexp(item.pattern), item); + } + if (item.children) { + for (const child of item.children) { + visit(child); + } + } + } + }; + for (const item of navigation) { + visit(item); + } + return map; +} +const itemLookupMapCache = new WeakMap>(); +function getItemLookup(navigation: Navigation) { + let map = itemLookupMapCache.get(navigation); + if (!map) { + map = buildItemLookup(navigation); + itemLookupMapCache.set(navigation, map); + } + return map; +} + +/** + * Matches a path against the navigation to find the active page. i.e. the page that should be + * marked as selected in the navigation. + */ +export function matchPath(navigation: Navigation, path: string): NavigationPageItem | null { + const lookup = getItemLookup(navigation); + + for (const [key, item] of lookup.entries()) { + if (typeof key === 'string' && key === path) { + return item; + } + if (key instanceof RegExp && key.test(path)) { + return item; + } + } + + return null; +} + +/** + * Gets the path for a specific navigation page item. + */ +export function getItemPath(navigation: Navigation, item: NavigationPageItem): string { + const map = getItemToPathMap(navigation); + const path = map.get(item); + invariant(path, `Item not found in navigation: ${item.title}`); + return path; +} diff --git a/packages/toolpad-core/src/useActivePage/index.ts b/packages/toolpad-core/src/useActivePage/index.ts new file mode 100644 index 00000000000..52662dbd290 --- /dev/null +++ b/packages/toolpad-core/src/useActivePage/index.ts @@ -0,0 +1 @@ +export * from './useActivePage'; diff --git a/packages/toolpad-core/src/useActivePage/useActivePage.ts b/packages/toolpad-core/src/useActivePage/useActivePage.ts new file mode 100644 index 00000000000..e1b6a9762d5 --- /dev/null +++ b/packages/toolpad-core/src/useActivePage/useActivePage.ts @@ -0,0 +1,54 @@ +'use client'; +import * as React from 'react'; +import { NavigationContext, RouterContext } from '../shared/context'; +import { getItemPath, getItemTitle, matchPath } from '../shared/navigation'; +import type { BreadCrumb } from '../PageContainer'; + +export function useActivePage() { + const navigationContext = React.useContext(NavigationContext); + const routerContext = React.useContext(RouterContext); + const pathname = routerContext?.pathname ?? '/'; + const activeItem = matchPath(navigationContext, pathname); + + const rootItem = matchPath(navigationContext, '/'); + + return React.useMemo(() => { + if (!activeItem) { + return null; + } + + const breadCrumbs: BreadCrumb[] = []; + + if (rootItem) { + breadCrumbs.push({ + title: getItemTitle(rootItem), + path: '/', + }); + } + + const segments = pathname.split('/').filter(Boolean); + let prefix = ''; + for (const segment of segments) { + const path = `${prefix}/${segment}`; + prefix = path; + const item = matchPath(navigationContext, path); + if (!item) { + continue; + } + const itemPath = getItemPath(navigationContext, item); + const lastCrumb = breadCrumbs[breadCrumbs.length - 1]; + if (lastCrumb?.path !== itemPath) { + breadCrumbs.push({ + title: getItemTitle(item), + path: itemPath, + }); + } + } + + return { + title: getItemTitle(activeItem), + path: getItemPath(navigationContext, activeItem), + breadCrumbs, + }; + }, [activeItem, rootItem, pathname, navigationContext]); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c0b4090e51f..0af1141a20b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,8 +98,8 @@ importers: specifier: 1.0.14 version: 1.0.14 '@mui/internal-scripts': - specifier: 1.0.21 - version: 1.0.21 + specifier: 1.0.21-dev.20240919-130050-82a6448768 + version: 1.0.21-dev.20240919-130050-82a6448768 '@mui/monorepo': specifier: github:mui/material-ui#3732be30e0ae3287b55dc6a96cf1ffcfdc194906 version: https://codeload.github.com/mui/material-ui/tar.gz/3732be30e0ae3287b55dc6a96cf1ffcfdc194906(encoding@0.1.13) @@ -195,7 +195,7 @@ importers: version: 7.35.2(eslint@8.57.0) eslint-plugin-react-compiler: specifier: latest - version: 0.0.0-experimental-7670337-20240918(eslint@8.57.0) + version: 0.0.0-experimental-92aaa43-20240919(eslint@8.57.0) eslint-plugin-react-hooks: specifier: 4.6.2 version: 4.6.2(eslint@8.57.0) @@ -2852,8 +2852,8 @@ packages: '@mui/internal-markdown@1.0.14': resolution: {integrity: sha512-Df8Uo54TyE7Lm3otWWxw2OQzv3ztbdhRJMJ2sCYrTDqluAvGe/65KpVr95/AcY/An3qWpvBrbn5k5Oj/NG/lXw==} - '@mui/internal-scripts@1.0.21': - resolution: {integrity: sha512-nVjt+Yjjff83C+urxDD63LmUhIR1bMbGVexHdFq1v9odyVKXw3tgL1yiCoEETLUfOkBbXECmjuRcbw+meWu5+g==} + '@mui/internal-scripts@1.0.21-dev.20240919-130050-82a6448768': + resolution: {integrity: sha512-feyp1s9pHvSOdO+ERv8oPGp2qGUCnngTt0+Yb+yTBo1tH8DN1Ks5JA7gIQR/elTnDusrbBQPpI7IAG5ZPrYlzQ==} '@mui/joy@5.0.0-beta.48': resolution: {integrity: sha512-OhTvjuGl9I5IvpBr0BQyDehIW/xb2yteW6YglHJMdOb/279nItn76X1NBtPV9ImldNlBjReGwvpOXmBTTGER9w==} @@ -5824,8 +5824,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-react-compiler@0.0.0-experimental-7670337-20240918: - resolution: {integrity: sha512-FZXoYqGK3BiJw2BFQIUL0C9GgEF2QS+y6oiVPm4GooX6SXrg/UVtCi1nMAaBhqTpsF/KF2RjobgePY8KgbqXow==} + eslint-plugin-react-compiler@0.0.0-experimental-92aaa43-20240919: + resolution: {integrity: sha512-l1tEUmxnZcMNkpUffbyNPAV91kZMZYLVeCCRZajK/s1QdP9FquunJQ9uT4c3f0RqdV6n0kloVfnJ0lPD1FTPlg==} engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} peerDependencies: eslint: '>=7' @@ -12040,7 +12040,7 @@ snapshots: marked: 13.0.3 prismjs: 1.29.0 - '@mui/internal-scripts@1.0.21': + '@mui/internal-scripts@1.0.21-dev.20240919-130050-82a6448768': dependencies: '@babel/core': 7.25.2 '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) @@ -15628,7 +15628,7 @@ snapshots: globals: 13.24.0 rambda: 7.5.0 - eslint-plugin-react-compiler@0.0.0-experimental-7670337-20240918(eslint@8.57.0): + eslint-plugin-react-compiler@0.0.0-experimental-92aaa43-20240919(eslint@8.57.0): dependencies: '@babel/core': 7.25.2 '@babel/parser': 7.25.6