diff --git a/docs/data/toolpad/core/all-components/all-components.md b/docs/data/toolpad/core/all-components/all-components.md new file mode 100644 index 00000000000..93b03bbce29 --- /dev/null +++ b/docs/data/toolpad/core/all-components/all-components.md @@ -0,0 +1,6 @@ +# Toolpad Core components + +

This page contains an index to the components included in Toolpad Core.

+ +- [App Provider](/toolpad/core/react-app-provider/) +- [Dashboard Layout](/toolpad/core/react-dashboard-layout/) diff --git a/docs/data/toolpad/core/api/components/data-grid.md b/docs/data/toolpad/core/api/components/data-grid.md deleted file mode 100644 index e902c50b49d..00000000000 --- a/docs/data/toolpad/core/api/components/data-grid.md +++ /dev/null @@ -1,3 +0,0 @@ -# Data Grid API - -

Data Grid API reference

diff --git a/docs/data/toolpad/core/api/components/line-chart.md b/docs/data/toolpad/core/api/components/line-chart.md deleted file mode 100644 index ed1c6f3fff9..00000000000 --- a/docs/data/toolpad/core/api/components/line-chart.md +++ /dev/null @@ -1,3 +0,0 @@ -# Line Chart API - -

Line Chart API reference

diff --git a/docs/data/toolpad/core/api/components/select-filter.md b/docs/data/toolpad/core/api/components/select-filter.md deleted file mode 100644 index 973de27a59a..00000000000 --- a/docs/data/toolpad/core/api/components/select-filter.md +++ /dev/null @@ -1,3 +0,0 @@ -# Select Filter API - -

Select Filter API reference

diff --git a/docs/data/toolpad/core/api/hooks/use-filter-state.md b/docs/data/toolpad/core/api/hooks/use-filter-state.md deleted file mode 100644 index 740d90bab03..00000000000 --- a/docs/data/toolpad/core/api/hooks/use-filter-state.md +++ /dev/null @@ -1,3 +0,0 @@ -# useFilterState API - -

useFilterState API reference

diff --git a/docs/data/toolpad/core/components/app-provider/app-provider.md b/docs/data/toolpad/core/components/app-provider/app-provider.md new file mode 100644 index 00000000000..b270053820d --- /dev/null +++ b/docs/data/toolpad/core/components/app-provider/app-provider.md @@ -0,0 +1,9 @@ +--- +productId: toolpad-core +title: App Provider +components: AppProvider +--- + +# App Provider + +

The app provider component provides the necessary context for a Toolpad application.

diff --git a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md index 86f2aeccf8b..21019e6becf 100644 --- a/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md +++ b/docs/data/toolpad/core/components/dashboard-layout/dashboard-layout.md @@ -1,3 +1,9 @@ +--- +productId: toolpad-core +title: Dashboard Layout +components: AppProvider, DashboardLayout +--- + # Dashboard Layout

The dashboard layout component provides a customizable out-of-the-box layout for a typical dashboard page.

diff --git a/docs/data/toolpad/core/components/data-grid.md b/docs/data/toolpad/core/components/data-grid.md deleted file mode 100644 index e29ba393d4f..00000000000 --- a/docs/data/toolpad/core/components/data-grid.md +++ /dev/null @@ -1,3 +0,0 @@ -# Data Grid - -

Data Grid component

diff --git a/docs/data/toolpad/core/components/line-chart.md b/docs/data/toolpad/core/components/line-chart.md deleted file mode 100644 index 7e38f59317a..00000000000 --- a/docs/data/toolpad/core/components/line-chart.md +++ /dev/null @@ -1,3 +0,0 @@ -# Line Chart - -

Line Chart component

diff --git a/docs/data/toolpad/core/components/select-filter.md b/docs/data/toolpad/core/components/select-filter.md deleted file mode 100644 index ac0ee99408f..00000000000 --- a/docs/data/toolpad/core/components/select-filter.md +++ /dev/null @@ -1,3 +0,0 @@ -# Select Filter - -

Select Filter component

diff --git a/docs/data/toolpad/core/pages.ts b/docs/data/toolpad/core/pages.ts index fc88395282b..85662776f49 100644 --- a/docs/data/toolpad/core/pages.ts +++ b/docs/data/toolpad/core/pages.ts @@ -60,38 +60,24 @@ const pages: MuiPage[] = [ pathname: '/toolpad/core/components-group', title: 'Components', children: [ - { pathname: '/toolpad/core/components', title: 'All components' }, + { pathname: '/toolpad/core/all-components', title: 'All components' }, { - pathname: '/toolpad/core/components/layout-group', - subheader: 'Layout', - children: [ - { - pathname: '/toolpad/core/components/dashboard-layout', - title: 'Dashboard Layout', - }, - ], - }, - { - pathname: '/toolpad/core/components/data-group', - subheader: 'Data', + pathname: '/toolpad/core/provider-group', + subheader: 'Provider', children: [ { - pathname: '/toolpad/core/components/data-grid', - title: 'Data Grid', - }, - { - pathname: '/toolpad/core/components/line-chart', - title: 'Line Chart', + pathname: '/toolpad/core/react-app-provider', + title: 'App Provider', }, ], }, { - pathname: '/toolpad/core/components/filter-group', - subheader: 'Filters', + pathname: '/toolpad/core/layout-group', + subheader: 'Layout', children: [ { - pathname: '/toolpad/core/components/select-filter', - title: 'Select', + pathname: '/toolpad/core/react-dashboard-layout', + title: 'Dashboard Layout', }, ], }, @@ -99,47 +85,19 @@ const pages: MuiPage[] = [ }, { pathname: '/toolpad/core/api-group', - title: 'API', + title: 'APIs', children: [ - { - pathname: '/toolpad/core/api', - title: 'Index', - }, { pathname: '/toolpad/core/api/components-group', subheader: 'Components', children: [ { - pathname: '/toolpad/core/api/dashboard-layout', - title: 'DashboardLayout', - }, - { - pathname: '/toolpad/core/api/data-grid', - title: 'Data Grid', - }, - { - pathname: '/toolpad/core/api/line-chart', - title: 'Line Chart', - }, - ], - }, - { - pathname: '/toolpad/core/api/filters-group', - subheader: 'Filters', - children: [ - { - pathname: '/toolpad/core/api/select-filter', - title: 'Select', + pathname: '/toolpad/core/api/app-provider', + title: 'AppProvider', }, - ], - }, - { - pathname: '/toolpad/core/api/hooks-group', - subheader: 'Hooks', - children: [ { - pathname: '/toolpad/core/api/use-filter-state', - title: 'useFilterState', + pathname: '/toolpad/core/api/dashboard-layout', + title: 'DashboardLayout', }, ], }, diff --git a/docs/data/toolpad/core/pagesApi.js b/docs/data/toolpad/core/pagesApi.js new file mode 100644 index 00000000000..6005be092d2 --- /dev/null +++ b/docs/data/toolpad/core/pagesApi.js @@ -0,0 +1,4 @@ +module.exports = [ + { pathname: '/toolpad/core/api/app-provider' }, + { pathname: '/toolpad/core/api/dashboard-layout' }, +]; diff --git a/docs/next.config.mjs b/docs/next.config.mjs index 5ed426f82a7..278d3f70fe7 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -2,6 +2,7 @@ import * as path from 'path'; import * as url from 'url'; import { createRequire } from 'module'; +import { LANGUAGES, LANGUAGES_IGNORE_PAGES, LANGUAGES_IN_PROGRESS } from './config.js'; const currentDirectory = url.fileURLToPath(new URL('.', import.meta.url)); @@ -57,6 +58,7 @@ export default withDocsInfra({ alias: { ...config.resolve.alias, docs: path.resolve(MONOREPO_PATH, './docs'), + 'docs-toolpad': path.resolve(WORKSPACE_ROOT, './docs'), ...MONOREPO_PACKAGES, '@toolpad/studio-components': path.resolve( currentDirectory, @@ -85,6 +87,14 @@ export default withDocsInfra({ loader: '@mui/internal-markdown/loader', options: { workspaceRoot: WORKSPACE_ROOT, + ignoreLanguagePages: LANGUAGES_IGNORE_PAGES, + languagesInProgress: LANGUAGES_IN_PROGRESS, + packages: [ + { + productId: 'toolpad-core', + paths: [path.join(WORKSPACE_ROOT, 'packages/toolpad-core/src')], + }, + ], env: { SOURCE_CODE_REPO: options.config.env.SOURCE_CODE_REPO, LIB_VERSION: options.config.env.LIB_VERSION, @@ -141,6 +151,12 @@ export default withDocsInfra({ output: 'export', } : { + rewrites: async () => { + return [ + { source: `/:lang(${LANGUAGES.join('|')})?/:rest*`, destination: '/:rest*' }, + { source: '/api/:rest*', destination: '/api-docs/:rest*' }, + ]; + }, redirects: async () => [ { source: '/', diff --git a/docs/pages/_app.js b/docs/pages/_app.js index ba4b51fb318..655eced45bc 100644 --- a/docs/pages/_app.js +++ b/docs/pages/_app.js @@ -19,7 +19,6 @@ import findActivePage from 'docs/src/modules/utils/findActivePage'; import getProductInfoFromUrl from 'docs/src/modules/utils/getProductInfoFromUrl'; import toolpadPkgJson from '@toolpad/studio/package.json'; import { DocsProvider } from '@mui/docs/DocsProvider'; -import { mapTranslations } from '@mui/docs/i18n'; import toolpadStudioPages from '../data/toolpad/studio/pages'; import toolpadCorePages from '../data/toolpad/core/pages'; import config from '../config'; @@ -260,11 +259,7 @@ function AppWrapper(props) { - + @@ -307,9 +302,6 @@ MyApp.propTypes = { MyApp.getInitialProps = async ({ ctx, Component }) => { let pageProps = {}; - const req = require.context('../translations', false, /translations.*\.json$/); - const translations = mapTranslations(req); - if (Component.getInitialProps) { pageProps = await Component.getInitialProps(ctx); } @@ -317,7 +309,6 @@ MyApp.getInitialProps = async ({ ctx, Component }) => { return { pageProps: { userLanguage: ctx.query.userLanguage || 'en', - translations, ...pageProps, }, }; diff --git a/docs/pages/toolpad/core/components/index.js b/docs/pages/toolpad/core/all-components/index.js similarity index 64% rename from docs/pages/toolpad/core/components/index.js rename to docs/pages/toolpad/core/all-components/index.js index 1dc199756c6..a69e1e9cad0 100644 --- a/docs/pages/toolpad/core/components/index.js +++ b/docs/pages/toolpad/core/all-components/index.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/components/index.md?muiMarkdown'; +import * as pageProps from 'docs-toolpad/data/toolpad/core/all-components/all-components.md?muiMarkdown'; export default function Page() { return ; diff --git a/docs/pages/toolpad/core/api/app-provider.js b/docs/pages/toolpad/core/api/app-provider.js new file mode 100644 index 00000000000..7912bfe8df4 --- /dev/null +++ b/docs/pages/toolpad/core/api/app-provider.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './app-provider.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docs-toolpad/translations/api-docs/app-provider', + false, + /\.\/app-provider.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/toolpad/core/api/app-provider.json b/docs/pages/toolpad/core/api/app-provider.json new file mode 100644 index 00000000000..0033851aff7 --- /dev/null +++ b/docs/pages/toolpad/core/api/app-provider.json @@ -0,0 +1,30 @@ +{ + "props": { + "children": { "type": { "name": "node" }, "required": true }, + "branding": { + "type": { "name": "shape", "description": "{ logo?: node, title?: string }" }, + "default": "null" + }, + "navigation": { + "type": { + "name": "arrayOf", + "description": "Array<{ children?: Array<object
| { kind: 'header', title: string }
| { kind: 'divider' }>, icon?: node, kind?: 'page', slug?: string, title: string }
| { kind: 'header', title: string }
| { kind: 'divider' }>" + }, + "default": "[]" + }, + "theme": { "type": { "name": "object" }, "default": "baseTheme" } + }, + "name": "AppProvider", + "imports": [ + "import { AppProvider } from '@toolpad-core/AppProvider';", + "import { AppProvider } from '@toolpad-core';" + ], + "classes": [], + "spread": true, + "themeDefaultProps": null, + "muiName": "AppProvider", + "filename": "/packages/toolpad-core/src/AppProvider/AppProvider.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/toolpad/core/api/dashboard-layout.js b/docs/pages/toolpad/core/api/dashboard-layout.js index 6eb70763b78..c7f6926f0d8 100644 --- a/docs/pages/toolpad/core/api/dashboard-layout.js +++ b/docs/pages/toolpad/core/api/dashboard-layout.js @@ -1,7 +1,23 @@ import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/api/components/dashboard-layout.md?muiMarkdown'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './dashboard-layout.json'; -export default function Page() { - return ; +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; } + +Page.getInitialProps = () => { + const req = require.context( + 'docs-toolpad/translations/api-docs/dashboard-layout', + false, + /\.\/dashboard-layout.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/toolpad/core/api/dashboard-layout.json b/docs/pages/toolpad/core/api/dashboard-layout.json new file mode 100644 index 00000000000..af4c4e66fda --- /dev/null +++ b/docs/pages/toolpad/core/api/dashboard-layout.json @@ -0,0 +1,16 @@ +{ + "props": { "children": { "type": { "name": "node" }, "required": true } }, + "name": "DashboardLayout", + "imports": [ + "import { DashboardLayout } from '@toolpad-core/DashboardLayout';", + "import { DashboardLayout } from '@toolpad-core';" + ], + "classes": [], + "spread": true, + "themeDefaultProps": null, + "muiName": "DashboardLayout", + "filename": "/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/toolpad/core/api/data-grid.js b/docs/pages/toolpad/core/api/data-grid.js deleted file mode 100644 index 95b8672b04f..00000000000 --- a/docs/pages/toolpad/core/api/data-grid.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/api/components/data-grid.md?muiMarkdown'; - -export default function Page() { - return ; -} diff --git a/docs/pages/toolpad/core/api/select-filter.js b/docs/pages/toolpad/core/api/select-filter.js deleted file mode 100644 index efc19d4c04e..00000000000 --- a/docs/pages/toolpad/core/api/select-filter.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/api/components/select-filter.md?muiMarkdown'; - -export default function Page() { - return ; -} diff --git a/docs/pages/toolpad/core/api/use-filter-state.js b/docs/pages/toolpad/core/api/use-filter-state.js deleted file mode 100644 index 4c51991c97a..00000000000 --- a/docs/pages/toolpad/core/api/use-filter-state.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/api/hooks/use-filter-state.md?muiMarkdown'; - -export default function Page() { - return ; -} diff --git a/docs/pages/toolpad/core/components/data-grid.js b/docs/pages/toolpad/core/components/data-grid.js deleted file mode 100644 index c041ee5e607..00000000000 --- a/docs/pages/toolpad/core/components/data-grid.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/components/data-grid.md?muiMarkdown'; - -export default function Page() { - return ; -} diff --git a/docs/pages/toolpad/core/components/line-chart.js b/docs/pages/toolpad/core/components/line-chart.js deleted file mode 100644 index e30fde27801..00000000000 --- a/docs/pages/toolpad/core/components/line-chart.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/components/line-chart.md?muiMarkdown'; - -export default function Page() { - return ; -} diff --git a/docs/pages/toolpad/core/components/select-filter.js b/docs/pages/toolpad/core/components/select-filter.js deleted file mode 100644 index 94b2b77b95e..00000000000 --- a/docs/pages/toolpad/core/components/select-filter.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/components/select-filter.md?muiMarkdown'; - -export default function Page() { - return ; -} diff --git a/docs/pages/toolpad/core/api/index.js b/docs/pages/toolpad/core/react-app-provider/index.js similarity index 62% rename from docs/pages/toolpad/core/api/index.js rename to docs/pages/toolpad/core/react-app-provider/index.js index 3fa29b840b3..8b2974aeddc 100644 --- a/docs/pages/toolpad/core/api/index.js +++ b/docs/pages/toolpad/core/react-app-provider/index.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/api/index.md?muiMarkdown'; +import * as pageProps from 'docs-toolpad/data/toolpad/core/components/app-provider/app-provider.md?muiMarkdown'; export default function Page() { return ; diff --git a/docs/pages/toolpad/core/api/line-chart.js b/docs/pages/toolpad/core/react-dashboard-layout/index.js similarity index 60% rename from docs/pages/toolpad/core/api/line-chart.js rename to docs/pages/toolpad/core/react-dashboard-layout/index.js index 5cbb34aeddb..34d1e499b4d 100644 --- a/docs/pages/toolpad/core/api/line-chart.js +++ b/docs/pages/toolpad/core/react-dashboard-layout/index.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/core/api/components/line-chart.md?muiMarkdown'; +import * as pageProps from 'docs-toolpad/data/toolpad/core/components/dashboard-layout/dashboard-layout.md?muiMarkdown'; export default function Page() { return ; diff --git a/docs/translations/api-docs/app-provider/app-provider.json b/docs/translations/api-docs/app-provider/app-provider.json new file mode 100644 index 00000000000..dc9d2445c14 --- /dev/null +++ b/docs/translations/api-docs/app-provider/app-provider.json @@ -0,0 +1,12 @@ +{ + "componentDescription": "", + "propDescriptions": { + "branding": { "description": "Branding options for the app." }, + "children": { "description": "The content of the app provider." }, + "navigation": { "description": "Navigation definition for the app." }, + "theme": { + "description": "Theme used by the app." + } + }, + "classDescriptions": {} +} diff --git a/docs/translations/api-docs/dashboard-layout/dashboard-layout.json b/docs/translations/api-docs/dashboard-layout/dashboard-layout.json new file mode 100644 index 00000000000..8e461ca2aaa --- /dev/null +++ b/docs/translations/api-docs/dashboard-layout/dashboard-layout.json @@ -0,0 +1,5 @@ +{ + "componentDescription": "", + "propDescriptions": { "children": { "description": "The content of the dashboard." } }, + "classDescriptions": {} +} diff --git a/eslintWebpackResolverConfig.js b/eslintWebpackResolverConfig.js index 88c5a02be65..eed621fd384 100644 --- a/eslintWebpackResolverConfig.js +++ b/eslintWebpackResolverConfig.js @@ -6,6 +6,10 @@ module.exports = { modules: [__dirname, 'node_modules'], alias: { '@mui/docs': path.resolve(__dirname, './node_modules/@mui/monorepo/packages/mui-docs/src'), + '@mui-internal/api-docs-builder': path.resolve( + __dirname, + './node_modules/@mui/monorepo/packages/api-docs-builder', + ), '@toolpad/studio-components': path.resolve( __dirname, './packages/toolpad-studio-components/src', @@ -14,6 +18,7 @@ module.exports = { '@toolpad/utils': path.resolve(__dirname, './packages/toolpad-utils/src'), '@toolpad/core': path.resolve(__dirname, './packages/toolpad-core/src'), docs: path.resolve(__dirname, './node_modules/@mui/monorepo/docs'), + 'docs-toolpad': path.resolve(__dirname, './docs'), }, extensions: ['.js', '.ts', '.tsx', '.d.ts'], }, diff --git a/package.json b/package.json index 55716b66ada..893113176eb 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "scripts": { "preinstall": "npx only-allow pnpm", + "proptypes": "tsx ./scripts/generateProptypes.ts", "install:codesandbox": "corepack enable && PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 pnpm install --no-frozen-lockfile", "markdownlint": "markdownlint-cli2 \"**/*.md\"", "prettier": "pretty-quick --ignore-path .eslintignore", @@ -17,7 +18,9 @@ "dev": "dotenv cross-env FORCE_COLOR=1 lerna -- run dev --stream --parallel --ignore docs", "docs:dev": "pnpm --filter docs dev", "docs:build": "pnpm --filter docs build", - "docs:build:api": "tsx --tsconfig ./scripts/tsconfig.json ./scripts/docs/buildApi.ts", + "docs:build:api:core": "tsx --tsconfig ./scripts/tsconfig.json ./scripts/docs/buildCoreApiDocs/index.ts", + "docs:build:api:studio": "tsx --tsconfig ./scripts/tsconfig.json ./scripts/docs/buildStudioApi.ts", + "docs:build:api": "concurrently \"pnpm docs:build:api:core\" \"pnpm docs:build:api:studio\"", "docs:typescript:formatted": "tsx ./docs/scripts/formattedTSDemos", "eslint": "eslint . --report-unused-disable-directives --ext .js,.ts,.tsx", "jsonlint": "node ./scripts/jsonlint.mjs", @@ -49,6 +52,7 @@ "@babel/preset-react": "7.24.1", "@babel/preset-typescript": "7.24.1", "@mui/internal-docs-utils": "1.0.7", + "@mui/internal-markdown": "1.0.3", "@mui/internal-scripts": "1.0.8", "@mui/monorepo": "github:mui/material-ui#2223961179a8812664c589e4ee8042f108bfc021", "@mui/x-charts": "7.5.0", @@ -60,11 +64,13 @@ "@types/gtag.js": "0.0.19", "@types/invariant": "2.2.37", "@types/node": "20.12.8", + "@types/yargs": "17.0.32", "@typescript-eslint/eslint-plugin": "7.9.0", "@typescript-eslint/parser": "7.9.0", "babel-plugin-react-remove-properties": "0.3.0", "babel-plugin-transform-react-remove-prop-types": "0.4.24", "chalk": "5.3.0", + "concurrently": "8.2.2", "eslint": "8.57.0", "eslint-config-airbnb": "19.0.4", "eslint-config-airbnb-typescript": "18.0.0", @@ -88,11 +94,14 @@ "markdownlint-cli2": "0.13.0", "prettier": "3.2.5", "pretty-quick": "4.0.0", + "react-docgen": "5.4.3", "react-inspector": "6.0.2", "recharts": "2.12.7", "regenerator-runtime": "0.14.1", + "remark": "13.0.0", "rimraf": "5.0.7", "typescript": "5.4.5", + "unist-util-visit": "2.0.3", "vitest-dom": "0.1.1", "vitest-fail-on-console": "0.7.0" }, diff --git a/packages/toolpad-core/package.json b/packages/toolpad-core/package.json index 7355a48beab..150b091d2d2 100644 --- a/packages/toolpad-core/package.json +++ b/packages/toolpad-core/package.json @@ -48,15 +48,16 @@ "dependencies": { "@toolpad/utils": "workspace:*", "client-only": "^0.0.1", - "invariant": "2.2.4" + "invariant": "2.2.4", + "prop-types": "15.8.1" }, "devDependencies": { "@mui/icons-material": "5.15.18", "@mui/material": "5.15.18", "@types/invariant": "2.2.37", + "@types/prop-types": "15.7.12", "@types/react": "18.3.1", - "@types/react-dom": "18.3.0", - "concurrently": "8.2.2" + "@types/react-dom": "18.3.0" }, "peerDependencies": { "@mui/icons-material": "^5", diff --git a/packages/toolpad-core/src/AppProvider/AppProvider.tsx b/packages/toolpad-core/src/AppProvider/AppProvider.tsx index 77e2d7cd7d9..c39d602f3af 100644 --- a/packages/toolpad-core/src/AppProvider/AppProvider.tsx +++ b/packages/toolpad-core/src/AppProvider/AppProvider.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { ThemeProvider, Theme } from '@mui/material/styles'; import CssBaseline from '@mui/material/CssBaseline'; import { baseTheme } from '../themes'; @@ -34,18 +35,41 @@ export const BrandingContext = React.createContext(null); export const NavigationContext = React.createContext([]); interface AppProviderProps { + /** + * The content of the app provider. + */ children: React.ReactNode; + /** + * [Theme](https://mui.com/material-ui/customization/theming/) used by the app. + * @default baseTheme + */ theme?: Theme; + /** + * Branding options for the app. + * @default null + */ branding?: Branding | null; + /** + * Navigation definition for the app. + * @default [] + */ navigation?: Navigation; } -export function AppProvider({ - children, - theme = baseTheme, - branding = null, - navigation = [], -}: AppProviderProps) { +/** + * + * Demos: + * + * - [App Provider](https://mui.com/toolpad/core/react-app-provider/) + * - [Dashboard Layout](https://mui.com/toolpad/core/react-dashboard-layout/) + * + * API: + * + * - [AppProvider API](https://mui.com/toolpad/core/api/app-provider) + */ +function AppProvider(props: AppProviderProps) { + const { children, theme = baseTheme, branding = null, navigation = [] } = props; + return ( @@ -55,3 +79,62 @@ export function AppProvider({ ); } + +AppProvider.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * Branding options for the app. + * @default null + */ + branding: PropTypes.shape({ + logo: PropTypes.node, + title: PropTypes.string, + }), + /** + * The content of the app provider. + */ + children: PropTypes.node, + /** + * Navigation definition for the app. + * @default [] + */ + navigation: PropTypes.arrayOf( + PropTypes.oneOfType([ + PropTypes.shape({ + children: PropTypes.arrayOf( + PropTypes.oneOfType([ + PropTypes.object, + PropTypes.shape({ + kind: PropTypes.oneOf(['header']).isRequired, + title: PropTypes.string.isRequired, + }), + PropTypes.shape({ + kind: PropTypes.oneOf(['divider']).isRequired, + }), + ]).isRequired, + ), + icon: PropTypes.node, + kind: PropTypes.oneOf(['page']), + slug: PropTypes.string, + title: PropTypes.string.isRequired, + }), + PropTypes.shape({ + kind: PropTypes.oneOf(['header']).isRequired, + title: PropTypes.string.isRequired, + }), + PropTypes.shape({ + kind: PropTypes.oneOf(['divider']).isRequired, + }), + ]).isRequired, + ), + /** + * [Theme](https://mui.com/material-ui/customization/theming/) used by the app. + * @default baseTheme + */ + theme: PropTypes.object, +} as any; + +export { AppProvider }; diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx index 8bc1def1159..1d9348dcb50 100644 --- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx +++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { styled } from '@mui/material'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; @@ -18,7 +19,6 @@ import Typography from '@mui/material/Typography'; import ExpandLessIcon from '@mui/icons-material/ExpandLess'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { BrandingContext, Navigation, NavigationContext, NavigationPageItem } from '../AppProvider'; -import ToolpadLogo from './ToolpadLogo'; const DRAWER_WIDTH = 320; @@ -48,6 +48,60 @@ const LogoContainer = styled('div')({ }, }); +function ToolpadLogo({ size = 40 }: { size?: number }) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + ); +} + interface DashboardSidebarSubNavigationProps { subNavigation: Navigation; basePath?: string; @@ -159,6 +213,7 @@ function DashboardSidebarSubNavigation({ ) : ( listItem )} + {navigationItem.children ? ( {/* - `1px solid ${theme.palette.divider}`, - }} - > - - - */} + `1px solid ${theme.palette.divider}`, + }} + > + + + */} ); } + +DashboardLayout.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * The content of the dashboard. + */ + children: PropTypes.node, +} as any; + +export { DashboardLayout }; diff --git a/packages/toolpad-core/src/DashboardLayout/ToolpadLogo.tsx b/packages/toolpad-core/src/DashboardLayout/ToolpadLogo.tsx deleted file mode 100644 index f5ed7d6a1d8..00000000000 --- a/packages/toolpad-core/src/DashboardLayout/ToolpadLogo.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import * as React from 'react'; - -export default function ToolpadLogo({ size = 40 }: { size?: number }) { - return ( - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/packages/toolpad-studio-runtime/package.json b/packages/toolpad-studio-runtime/package.json index 8564497cab8..61e2d3f87c3 100644 --- a/packages/toolpad-studio-runtime/package.json +++ b/packages/toolpad-studio-runtime/package.json @@ -61,8 +61,7 @@ "@types/express": "4.17.21", "@types/invariant": "2.2.37", "@types/react": "18.3.1", - "@types/react-is": "18.3.0", - "concurrently": "8.2.2" + "@types/react-is": "18.3.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b4a90f4eb2..53ef07dbea1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,6 +90,9 @@ importers: '@mui/internal-docs-utils': specifier: 1.0.7 version: 1.0.7 + '@mui/internal-markdown': + specifier: 1.0.3 + version: 1.0.3 '@mui/internal-scripts': specifier: 1.0.8 version: 1.0.8 @@ -123,6 +126,9 @@ importers: '@types/node': specifier: 20.12.8 version: 20.12.8 + '@types/yargs': + specifier: 17.0.32 + version: 17.0.32 '@typescript-eslint/eslint-plugin': specifier: 7.9.0 version: 7.9.0(@typescript-eslint/parser@7.9.0)(eslint@8.57.0)(typescript@5.4.5) @@ -138,6 +144,9 @@ importers: chalk: specifier: 5.3.0 version: 5.3.0 + concurrently: + specifier: 8.2.2 + version: 8.2.2 eslint: specifier: 8.57.0 version: 8.57.0 @@ -207,6 +216,9 @@ importers: pretty-quick: specifier: 4.0.0 version: 4.0.0(prettier@3.2.5) + react-docgen: + specifier: 5.4.3 + version: 5.4.3 react-inspector: specifier: 6.0.2 version: 6.0.2(react@18.2.0) @@ -216,12 +228,18 @@ importers: regenerator-runtime: specifier: 0.14.1 version: 0.14.1 + remark: + specifier: 13.0.0 + version: 13.0.0 rimraf: specifier: 5.0.7 version: 5.0.7 typescript: specifier: 5.4.5 version: 5.4.5 + unist-util-visit: + specifier: 2.0.3 + version: 2.0.3 vitest-dom: specifier: 0.1.1 version: 0.1.1(vitest@1.6.0) @@ -266,7 +284,7 @@ importers: version: 5.15.18(@mui/material@5.15.18)(@types/react@18.3.1)(react@18.2.0) '@mui/internal-markdown': specifier: ^1.0.1 - version: 1.0.1 + version: 1.0.3 '@mui/joy': specifier: 5.0.0-beta.36 version: 5.0.0-beta.36(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.1)(react-dom@18.2.0)(react@18.2.0) @@ -552,6 +570,9 @@ importers: invariant: specifier: 2.2.4 version: 2.2.4 + prop-types: + specifier: 15.8.1 + version: 15.8.1 react: specifier: ^18 version: 18.2.0 @@ -565,15 +586,15 @@ importers: '@types/invariant': specifier: 2.2.37 version: 2.2.37 + '@types/prop-types': + specifier: 15.7.12 + version: 15.7.12 '@types/react': specifier: 18.3.1 version: 18.3.1 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 - concurrently: - specifier: 8.2.2 - version: 8.2.2 packages/toolpad-studio: dependencies: @@ -1048,9 +1069,6 @@ importers: '@types/react-is': specifier: 18.3.0 version: 18.3.0 - concurrently: - specifier: 8.2.2 - version: 8.2.2 packages/toolpad-utils: dependencies: @@ -2706,6 +2724,10 @@ packages: '@babel/helper-validator-identifier': 7.24.5 to-fast-properties: 2.0.0 + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + /@date-io/core@3.0.0: resolution: {integrity: sha512-S3j+IAQVBYNkQzchVVhX40eBkGDreBpScy9RXwTS5j2+k07+62pMVPisQ44Gq76Rqy5AOG/EZXCwBpY/jbemvA==} dev: false @@ -3576,6 +3598,11 @@ packages: wrap-ansi: 8.1.0 wrap-ansi-cjs: /wrap-ansi@7.0.0 + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + /@jest/schemas@29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -3853,15 +3880,6 @@ packages: typescript: 5.4.5 dev: true - /@mui/internal-markdown@1.0.1: - resolution: {integrity: sha512-goTCzEbx0yxDbCU9ngHo02f5TBHwngF6RDM2ALqtgUsvNp14/lVU3OFytvpxcwjeSrrbVPEw4MSidYO8FnlUKQ==} - dependencies: - '@babel/runtime': 7.24.5 - lodash: 4.17.21 - marked: 5.1.2 - prismjs: 1.29.0 - dev: false - /@mui/internal-markdown@1.0.3: resolution: {integrity: sha512-b+8T8S1raSuaOXaNyKiChyw1Lb/nEY1ITGsw6oygVLacsN6mZ7EB5cmvEbHA4EQiNwqCn7BgI9OoBTTr0GdZtg==} dependencies: @@ -3869,7 +3887,6 @@ packages: lodash: 4.17.21 marked: 5.1.2 prismjs: 1.29.0 - dev: false /@mui/internal-scripts@1.0.8: resolution: {integrity: sha512-oWiDtSZyFoqhft6V03/5rcwe0WHOY23A4yZ+CUbTV0anPjSb5/N1aws2Bgkc9m69aqyZqhRYRhLlTweVIxOCPw==} @@ -6093,6 +6110,10 @@ packages: '@types/node': 20.12.11 dev: true + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -6120,6 +6141,12 @@ packages: /@types/lodash@4.17.1: resolution: {integrity: sha512-X+2qazGS3jxLAIz5JDXDzglAF3KpijdhFxlf/V1+hEsOUc+HnWi81L/uv/EvGuV90WY+7mPGFCUDGfQC3Gj95Q==} + /@types/mdast@3.0.15: + resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} + dependencies: + '@types/unist': 2.0.10 + dev: true + /@types/mime@1.3.5: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} @@ -6313,6 +6340,10 @@ packages: source-map: 0.6.1 dev: false + /@types/unist@2.0.10: + resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + dev: true + /@types/webidl-conversions@7.0.3: resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} dev: true @@ -7231,7 +7262,6 @@ packages: engines: {node: '>=4'} dependencies: tslib: 2.6.2 - dev: false /ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} @@ -7378,6 +7408,10 @@ packages: /babel-plugin-transform-react-remove-prop-types@0.4.24: resolution: {integrity: sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==} + /bail@1.0.5: + resolution: {integrity: sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==} + dev: true + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -7586,6 +7620,25 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + /c8@7.14.0: + resolution: {integrity: sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw==} + engines: {node: '>=10.12.0'} + hasBin: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@istanbuljs/schema': 0.1.3 + find-up: 5.0.0 + foreground-child: 2.0.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.1.7 + rimraf: 3.0.2 + test-exclude: 6.0.0 + v8-to-istanbul: 9.2.0 + yargs: 16.2.0 + yargs-parser: 20.2.9 + dev: true + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -7723,6 +7776,18 @@ packages: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + /character-entities-legacy@1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + dev: true + + /character-entities@1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + dev: true + + /character-reference-invalid@1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + dev: true + /chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} @@ -9457,6 +9522,17 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + /estree-to-babel@3.2.1: + resolution: {integrity: sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg==} + engines: {node: '>=8.3.0'} + dependencies: + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 + c8: 7.14.0 + transitivePeerDependencies: + - supports-color + dev: true + /estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} dependencies: @@ -9811,6 +9887,14 @@ packages: dependencies: is-callable: 1.2.7 + /foreground-child@2.0.0: + resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} + engines: {node: '>=8.0.0'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 3.0.7 + dev: true + /foreground-child@3.1.1: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} @@ -10496,7 +10580,6 @@ packages: /html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: false /html-tokenize@2.0.1: resolution: {integrity: sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==} @@ -10793,6 +10876,17 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + /is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + dev: true + + /is-alphanumerical@1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + dev: true + /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -10840,6 +10934,11 @@ packages: call-bind: 1.0.7 has-tostringtag: 1.0.2 + /is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: true + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -10868,6 +10967,10 @@ packages: dependencies: has-tostringtag: 1.0.2 + /is-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + dev: true + /is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -10904,6 +11007,10 @@ packages: dependencies: is-extglob: 2.1.1 + /is-hexadecimal@1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + dev: true + /is-in-browser@1.1.3: resolution: {integrity: sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==} dev: false @@ -10953,6 +11060,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: true + /is-plain-obj@3.0.0: resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} engines: {node: '>=10'} @@ -11099,6 +11211,28 @@ packages: engines: {node: '>=0.10.0'} dev: true + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + /iterate-iterator@1.0.2: resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==} dev: true @@ -11855,6 +11989,10 @@ packages: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} dev: false + /longest-streak@2.0.4: + resolution: {integrity: sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==} + dev: true + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -12051,7 +12189,33 @@ packages: resolution: {integrity: sha512-ahRPGXJpjMjwSOlBoTMZAK7ATXkli5qCPxZ21TG44rx1KEo44bii4ekgTDQPNRQ4Kh7JMb9Ub1PVk1NxRSsorg==} engines: {node: '>= 16'} hasBin: true - dev: false + + /mdast-util-from-markdown@0.8.5: + resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-string: 2.0.0 + micromark: 2.11.4 + parse-entities: 2.0.0 + unist-util-stringify-position: 2.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /mdast-util-to-markdown@0.6.5: + resolution: {integrity: sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==} + dependencies: + '@types/unist': 2.0.10 + longest-streak: 2.0.4 + mdast-util-to-string: 2.0.0 + parse-entities: 2.0.0 + repeat-string: 1.6.1 + zwitch: 1.0.5 + dev: true + + /mdast-util-to-string@2.0.0: + resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} + dev: true /mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} @@ -12107,6 +12271,15 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} + /micromark@2.11.4: + resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} + dependencies: + debug: 4.3.4 + parse-entities: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -12487,6 +12660,13 @@ packages: resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} dev: true + /node-dir@0.1.17: + resolution: {integrity: sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==} + engines: {node: '>= 0.10.5'} + dependencies: + minimatch: 3.1.2 + dev: true + /node-environment-flags@1.0.6: resolution: {integrity: sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==} dependencies: @@ -13192,6 +13372,17 @@ packages: dependencies: callsites: 3.1.0 + /parse-entities@2.0.0: + resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + dev: true + /parse-json@4.0.0: resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} engines: {node: '>=4'} @@ -13656,7 +13847,6 @@ packages: /prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} - dev: false /proc-log@3.0.0: resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} @@ -13880,6 +14070,25 @@ packages: - vue-template-compiler dev: false + /react-docgen@5.4.3: + resolution: {integrity: sha512-xlLJyOlnfr8lLEEeaDZ+X2J/KJoe6Nr9AzxnkdQWush5hz2ZSu66w6iLMOScMmxoSHWpWMn+k3v5ZiyCfcWsOA==} + engines: {node: '>=8.10.0'} + hasBin: true + dependencies: + '@babel/core': 7.24.5 + '@babel/generator': 7.24.5 + '@babel/runtime': 7.24.5 + ast-types: 0.14.2 + commander: 2.20.3 + doctrine: 3.0.0 + estree-to-babel: 3.2.1 + neo-async: 2.6.2 + node-dir: 0.1.17 + strip-indent: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /react-docgen@7.0.3: resolution: {integrity: sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==} engines: {node: '>=16.14.0'} @@ -14293,6 +14502,35 @@ packages: jsesc: 0.5.0 dev: true + /remark-parse@9.0.0: + resolution: {integrity: sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==} + dependencies: + mdast-util-from-markdown: 0.8.5 + transitivePeerDependencies: + - supports-color + dev: true + + /remark-stringify@9.0.1: + resolution: {integrity: sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==} + dependencies: + mdast-util-to-markdown: 0.6.5 + dev: true + + /remark@13.0.0: + resolution: {integrity: sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==} + dependencies: + remark-parse: 9.0.0 + remark-stringify: 9.0.1 + unified: 9.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -15352,6 +15590,15 @@ packages: commander: 2.20.3 source-map-support: 0.5.21 + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + /text-extensions@1.9.0: resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} engines: {node: '>=0.10'} @@ -15489,6 +15736,10 @@ packages: engines: {node: '>=8'} dev: true + /trough@1.0.5: + resolution: {integrity: sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==} + dev: true + /ts-api-utils@1.3.0(typescript@5.4.5): resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -15786,6 +16037,18 @@ packages: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} + /unified@9.2.2: + resolution: {integrity: sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==} + dependencies: + '@types/unist': 2.0.10 + bail: 1.0.5 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 2.1.0 + trough: 1.0.5 + vfile: 4.2.1 + dev: true + /unique-filename@2.0.1: resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -15814,6 +16077,31 @@ packages: imurmurhash: 0.1.4 dev: true + /unist-util-is@4.1.0: + resolution: {integrity: sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==} + dev: true + + /unist-util-stringify-position@2.0.3: + resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + dependencies: + '@types/unist': 2.0.10 + dev: true + + /unist-util-visit-parents@3.1.1: + resolution: {integrity: sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==} + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 4.1.0 + dev: true + + /unist-util-visit@2.0.3: + resolution: {integrity: sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==} + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 4.1.0 + unist-util-visit-parents: 3.1.1 + dev: true + /universal-user-agent@6.0.1: resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} dev: true @@ -15897,6 +16185,15 @@ packages: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} dev: true + /v8-to-istanbul@9.2.0: + resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + /v8flags@3.2.0: resolution: {integrity: sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==} engines: {node: '>= 0.10'} @@ -15928,6 +16225,22 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + /vfile-message@2.0.4: + resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} + dependencies: + '@types/unist': 2.0.10 + unist-util-stringify-position: 2.0.3 + dev: true + + /vfile@4.2.1: + resolution: {integrity: sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==} + dependencies: + '@types/unist': 2.0.10 + is-buffer: 2.0.5 + unist-util-stringify-position: 2.0.3 + vfile-message: 2.0.4 + dev: true + /victory-vendor@36.9.2: resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} dependencies: @@ -16601,6 +16914,10 @@ packages: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false + /zwitch@1.0.5: + resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} + dev: true + github.com/mui/material-ui/2223961179a8812664c589e4ee8042f108bfc021(@opentelemetry/api@1.8.0): resolution: {tarball: https://codeload.github.com/mui/material-ui/tar.gz/2223961179a8812664c589e4ee8042f108bfc021} id: github.com/mui/material-ui/2223961179a8812664c589e4ee8042f108bfc021 diff --git a/scripts/docs/buildApi.ts b/scripts/docs/buildApi.ts deleted file mode 100644 index 99e2706655d..00000000000 --- a/scripts/docs/buildApi.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { buildComponentsReference } from './buildComponentsReference'; - -async function main() { - await buildComponentsReference(); -} - -main().catch((err) => { - console.error(err); - process.exit(1); -}); diff --git a/scripts/docs/buildCoreApiDocs/config/getComponentImports.ts b/scripts/docs/buildCoreApiDocs/config/getComponentImports.ts new file mode 100644 index 00000000000..99ba5ac7daf --- /dev/null +++ b/scripts/docs/buildCoreApiDocs/config/getComponentImports.ts @@ -0,0 +1,29 @@ +import path from 'path'; + +const repositoryRoot = path.resolve(__dirname, '../../../..'); + +export function getComponentImports(name: string, filename: string) { + const relativePath = path.relative(repositoryRoot, filename); + const directories = path.dirname(relativePath).split(path.sep); + if ( + directories[0] !== 'packages' || + directories[1] !== 'toolpad-core' || + directories[2] !== 'src' + ) { + throw new Error(`The file ${filename} is not in the Toolpad Core package`); + } + + if (directories.length < 4) { + throw new Error(`The file ${filename} is not in a subdirectory of packages/toolpad-core/src`); + } + + const componentDirectory = directories[3]; + if (componentDirectory === name) { + return [ + `import { ${name} } from '@toolpad-core/${name}';`, + `import { ${name} } from '@toolpad-core';`, + ]; + } + + return [`import { ${name} } from '@toolpad-core/${componentDirectory}';`]; +} diff --git a/scripts/docs/buildCoreApiDocs/config/getCoreComponentInfo.ts b/scripts/docs/buildCoreApiDocs/config/getCoreComponentInfo.ts new file mode 100644 index 00000000000..a8fc142044e --- /dev/null +++ b/scripts/docs/buildCoreApiDocs/config/getCoreComponentInfo.ts @@ -0,0 +1,64 @@ +import fs from 'fs'; +import path from 'path'; +import kebabCase from 'lodash/kebabCase'; +import { getHeaders, getTitle } from '@mui/internal-markdown'; +import { + ComponentInfo, + extractPackageFile, + fixPathname, + parseFile, +} from '@mui-internal/api-docs-builder/buildApiUtils'; +import findPagesMarkdown from '@mui-internal/api-docs-builder/utils/findPagesMarkdown'; + +const REPO_ROOT = path.resolve(__dirname, '../../../..'); + +export function getCoreDemos(name: string) { + // resolve demos, so that we can getch the API url + const allMarkdowns = findPagesMarkdown(path.join(REPO_ROOT, 'docs/data/toolpad')) + .filter((markdown) => { + return markdown.filename.match(/[\\/]data[\\/]toolpad[\\/]core[\\/]/); + }) + .map((markdown) => { + const markdownContent = fs.readFileSync(markdown.filename, 'utf8'); + const markdownHeaders = getHeaders(markdownContent) as any; + + return { + ...markdown, + markdownContent, + components: markdownHeaders.components as string[], + }; + }); + return allMarkdowns + .filter((page) => page.components.includes(name)) + .map((page) => ({ + demoPageTitle: getTitle(page.markdownContent), + demoPathname: fixPathname(page.pathname), + })); +} + +export function getCoreComponentInfo(filename: string): ComponentInfo { + const { name } = extractPackageFile(filename); + let srcInfo: null | ReturnType = null; + if (!name) { + throw new Error(`Could not find the component name from: ${filename}`); + } + + const demos = getCoreDemos(name); + + return { + filename, + name, + muiName: name, + apiPathname: `/toolpad/core/api/${kebabCase(name)}`, + apiPagesDirectory: path.join(process.cwd(), `docs/pages/toolpad/core/api`), + isSystemComponent: false, + readFile: () => { + srcInfo = parseFile(filename); + return srcInfo; + }, + getInheritance: () => { + return null; + }, + getDemos: () => demos, + }; +} diff --git a/scripts/docs/buildCoreApiDocs/config/projectSettings.ts b/scripts/docs/buildCoreApiDocs/config/projectSettings.ts new file mode 100644 index 00000000000..2d2bc4816f3 --- /dev/null +++ b/scripts/docs/buildCoreApiDocs/config/projectSettings.ts @@ -0,0 +1,29 @@ +import path from 'path'; +import { ProjectSettings } from '@mui-internal/api-docs-builder'; +import findApiPages from '@mui-internal/api-docs-builder/utils/findApiPages'; +import { LANGUAGES } from '../../../../docs/config'; +import { getCoreComponentInfo } from './getCoreComponentInfo'; +import { getComponentImports } from './getComponentImports'; + +export const projectSettings: ProjectSettings = { + output: { + apiManifestPath: path.join(process.cwd(), 'docs/data/toolpad/core/pagesApi.js'), + }, + typeScriptProjects: [ + { + name: 'toolpad-core', + rootPath: path.join(process.cwd(), 'packages/toolpad-core'), + entryPointPath: 'src/index.ts', + }, + ], + getApiPages: () => findApiPages('docs/pages/toolpad/core/api'), + getComponentInfo: getCoreComponentInfo, + getComponentImports, + translationLanguages: LANGUAGES, + skipComponent: () => false, + skipSlotsAndClasses: true, + translationPagesDirectory: 'docs/translations/api-docs', + importTranslationPagesDirectory: 'docs-toolpad/translations/api-docs', + generateClassName: () => '', + isGlobalClassName: () => false, +}; diff --git a/scripts/docs/buildCoreApiDocs/index.ts b/scripts/docs/buildCoreApiDocs/index.ts new file mode 100644 index 00000000000..616b40e702e --- /dev/null +++ b/scripts/docs/buildCoreApiDocs/index.ts @@ -0,0 +1,28 @@ +import yargs, { ArgumentsCamelCase } from 'yargs'; +import { buildApi } from '@mui-internal/api-docs-builder'; +import { projectSettings } from './config/projectSettings'; + +type CommandOptions = { grep?: string }; + +async function run(argv: ArgumentsCamelCase) { + const grep = argv.grep == null ? null : new RegExp(argv.grep); + return buildApi([projectSettings], grep); +} + +yargs(process.argv.slice(2)) + .command({ + command: '$0', + describe: 'Generates API documentation for the MUI packages.', + builder: (command) => { + return command.option('grep', { + description: + 'Only generate files for component filenames matching the pattern. The string is treated as a RegExp.', + type: 'string', + }); + }, + handler: run, + }) + .help() + .strict(true) + .version(false) + .parse(); diff --git a/scripts/docs/buildStudioApi.ts b/scripts/docs/buildStudioApi.ts new file mode 100644 index 00000000000..e6503c3ba22 --- /dev/null +++ b/scripts/docs/buildStudioApi.ts @@ -0,0 +1,10 @@ +import { buildStudioComponentsReference } from './buildStudioComponentsReference'; + +async function main() { + await buildStudioComponentsReference(); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/scripts/docs/buildComponentsReference.ts b/scripts/docs/buildStudioComponentsReference.ts similarity index 98% rename from scripts/docs/buildComponentsReference.ts rename to scripts/docs/buildStudioComponentsReference.ts index bc9991063ce..b8ced25b706 100644 --- a/scripts/docs/buildComponentsReference.ts +++ b/scripts/docs/buildStudioComponentsReference.ts @@ -36,7 +36,7 @@ export default function Page() { ); } -export async function buildComponentsReference() { +export async function buildStudioComponentsReference() { await fs.rm(componentDocsRoot, { recursive: true, force: true }); await fs.mkdir(componentDocsRoot, { recursive: true }); await fs.rm(componentPagesRoot, { recursive: true, force: true }); diff --git a/scripts/generateProptypes.ts b/scripts/generateProptypes.ts new file mode 100644 index 00000000000..7985c8ba0be --- /dev/null +++ b/scripts/generateProptypes.ts @@ -0,0 +1,253 @@ +/* eslint-disable no-console */ +import * as path from 'path'; +import * as fse from 'fs-extra'; +import * as prettier from 'prettier'; +import glob from 'fast-glob'; +import * as _ from 'lodash'; +import * as yargs from 'yargs'; +import * as ts from 'typescript'; +import { fixBabelGeneratorIssues, fixLineEndings } from '@mui/internal-docs-utils'; +import { + getPropTypesFromFile, + injectPropTypesInFile, + InjectPropTypesInFileOptions, +} from '@mui/internal-scripts/typescript-to-proptypes'; +import { + createTypeScriptProjectBuilder, + TypeScriptProject, +} from '@mui-internal/api-docs-builder/utils/createTypeScriptProject'; + +import CORE_TYPESCRIPT_PROJECTS from './coreTypescriptProjects'; + +function sortSizeByScaleAscending(a: ts.LiteralType, b: ts.LiteralType) { + const sizeOrder: readonly unknown[] = ['"small"', '"medium"', '"large"']; + return sizeOrder.indexOf(a.value) - sizeOrder.indexOf(b.value); +} + +// Custom order of literal unions by component +const getSortLiteralUnions: InjectPropTypesInFileOptions['getSortLiteralUnions'] = ( + component, + propType, +) => { + if (propType.name === 'size') { + return sortSizeByScaleAscending; + } + + return undefined; +}; + +async function generateProptypes( + project: TypeScriptProject, + sourceFile: string, + tsFile: string, +): Promise { + const components = getPropTypesFromFile({ + filePath: tsFile, + project, + shouldResolveObject: ({ name }) => { + if ( + name.toLowerCase().endsWith('classes') || + name === 'theme' || + name === 'ownerState' || + (name.endsWith('Props') && name !== 'componentsProps' && name !== 'slotProps') + ) { + return false; + } + return undefined; + }, + checkDeclarations: true, + }); + + if (components.length === 0) { + return; + } + + // exclude internal slot components, for example ButtonRoot + const cleanComponents = components.filter((component) => { + if (component.propsFilename?.endsWith('.tsx')) { + // only check for .tsx + const match = component.propsFilename.match(/.*\/([A-Z][a-zA-Z]+)\.tsx/); + if (match) { + return component.name === match[1]; + } + } + return true; + }); + + cleanComponents.forEach((component) => { + component.types.forEach((prop) => { + if (!prop.jsDoc) { + prop.jsDoc = '@ignore'; + } + }); + }); + + const sourceContent = await fse.readFile(sourceFile, 'utf8'); + const isTsFile = /(\.(ts|tsx))/.test(sourceFile); + + // TODO remove, should only have .types.ts + const propsFile = tsFile.replace(/(\.d\.ts|\.tsx|\.ts)/g, 'Props.ts'); + const propsFileAlternative = tsFile.replace(/(\.d\.ts|\.tsx|\.ts)/g, '.types.ts'); + const generatedForTypeScriptFile = sourceFile === tsFile; + const result = injectPropTypesInFile({ + components: cleanComponents, + target: sourceContent, + options: { + disablePropTypesTypeChecking: generatedForTypeScriptFile, + babelOptions: { + filename: sourceFile, + }, + comment: [ + '┌────────────────────────────── Warning ──────────────────────────────┐', + '│ These PropTypes are generated from the TypeScript type definitions. │', + isTsFile + ? '│ To update them, edit the TypeScript types and run `pnpm proptypes`. │' + : '│ To update them, edit the d.ts file and run `pnpm proptypes`. │', + '└─────────────────────────────────────────────────────────────────────┘', + ].join('\n'), + ensureBabelPluginTransformReactRemovePropTypesIntegration: true, + getSortLiteralUnions, + reconcilePropTypes: (prop, previous, generated) => { + const usedCustomValidator = previous !== undefined && !previous.startsWith('PropTypes'); + const ignoreGenerated = + previous !== undefined && + previous.startsWith('PropTypes /* @typescript-to-proptypes-ignore */'); + + if ( + ignoreGenerated && + // `ignoreGenerated` implies that `previous !== undefined` + previous! + .replace('PropTypes /* @typescript-to-proptypes-ignore */', 'PropTypes') + .replace(/\s/g, '') === generated.replace(/\s/g, '') + ) { + throw new Error( + `Unused \`@typescript-to-proptypes-ignore\` directive for prop '${prop.name}'.`, + ); + } + + if (usedCustomValidator || ignoreGenerated) { + // `usedCustomValidator` and `ignoreGenerated` narrow `previous` to `string` + return previous!; + } + + return generated; + }, + shouldInclude: ({ prop }) => { + if (prop.name === 'children') { + return true; + } + let shouldDocument; + + prop.filenames.forEach((filename) => { + const isExternal = filename !== tsFile; + const implementedBySelfPropsFile = + filename === propsFile || filename === propsFileAlternative; + if (!isExternal || implementedBySelfPropsFile) { + shouldDocument = true; + } + }); + + return shouldDocument; + }, + }, + }); + + if (!result) { + throw new Error('Unable to produce inject propTypes into code.'); + } + + const prettierConfig = await prettier.resolveConfig(process.cwd(), { + config: path.join(__dirname, '../prettier.config.js'), + }); + + const prettified = await prettier.format(result, { ...prettierConfig, filepath: sourceFile }); + const formatted = fixBabelGeneratorIssues(prettified); + const correctedLineEndings = fixLineEndings(sourceContent, formatted); + + await fse.writeFile(sourceFile, correctedLineEndings); +} + +interface HandlerArgv { + pattern: string; +} +async function run(argv: HandlerArgv) { + const { pattern } = argv; + + const filePattern = new RegExp(pattern); + if (pattern.length > 0) { + console.log(`Only considering declaration files matching ${filePattern}`); + } + + const buildProject = createTypeScriptProjectBuilder(CORE_TYPESCRIPT_PROJECTS); + + // Matches files where the folder and file both start with uppercase letters + // Example: AppBar/AppBar.d.ts + const allFiles = await Promise.all( + [path.resolve(__dirname, '../packages/toolpad-core/src')].map((folderPath) => + glob('+([A-Z])*/+([A-Z])*.*@(d.ts|ts|tsx)', { + absolute: true, + cwd: folderPath, + }), + ), + ); + + const files = _.flatten(allFiles) + .filter((filePath) => { + // Filter out files where the directory name and filename doesn't match + // Example: Modal/ModalManager.d.ts + let folderName = path.basename(path.dirname(filePath)); + const fileName = path.basename(filePath).replace(/(\.d\.ts|\.tsx|\.ts)/g, ''); + + // An exception is if the folder name starts with Unstable_/unstable_ + // Example: Unstable_Grid2/Grid2.tsx + if (/(u|U)nstable_/g.test(folderName)) { + folderName = folderName.slice(9); + } + + return fileName === folderName; + }) + .filter((filePath) => filePattern.test(filePath)); + + const promises = files.map>(async (tsFile) => { + const sourceFile = tsFile.includes('.d.ts') ? tsFile.replace('.d.ts', '.js') : tsFile; + try { + const projectName = tsFile.match(/packages\/([a-zA-Z-]+)\/src/)![1]; + const project = buildProject(projectName); + await generateProptypes(project, sourceFile, tsFile); + } catch (error: any) { + error.message = `${tsFile}: ${error.message}`; + throw error; + } + }); + + const results = await Promise.allSettled(promises); + + const fails = results.filter((result): result is PromiseRejectedResult => { + return result.status === 'rejected'; + }); + + fails.forEach((result) => { + console.error(result.reason); + }); + if (fails.length > 0) { + process.exit(1); + } +} + +yargs + .command({ + command: '$0', + describe: 'Generates Component.propTypes from TypeScript declarations', + builder: (command) => { + return command.option('pattern', { + default: '', + describe: 'Only considers declaration files matching this pattern.', + type: 'string', + }); + }, + handler: run, + }) + .help() + .strict(true) + .version(false) + .parse(); diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index 1db844111cc..035dcfc6201 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "allowJs": true, "paths": { "@toolpad/studio-components": ["../packages/toolpad-studio-components/src/index.tsx"], "@toolpad/studio-runtime": ["../packages/toolpad-studio-runtime/src/index.tsx"], @@ -12,6 +13,13 @@ "@toolpad/utils/*": [ "../packages/toolpad-utils/src/*.tsx", "../packages/toolpad-utils/src/*.ts" + ], + "@mui-internal/api-docs-builder": ["../node_modules/@mui/monorepo/packages/api-docs-builder"], + "@mui-internal/api-docs-builder/*": [ + "../node_modules/@mui/monorepo/packages/api-docs-builder/*" + ], + "@mui/internal-scripts/typescript-to-proptypes": [ + "../node_modules/@mui/monorepo/packages-internal/scripts/typescript-to-proptypes/src" ] }, "module": "ESNext", diff --git a/tsconfig.json b/tsconfig.json index 05b81e55d97..5384765ab94 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,7 @@ "paths": { "@toolpad/core": ["./packages/toolpad-core/src"], "@toolpad/core/*": ["./packages/toolpad-core/src/*"], + "docs-toolpad/*": ["./docs/*"], "@mui-internal/api-docs-builder": ["./node_modules/@mui/monorepo/packages/api-docs-builder"], "@mui-internal/api-docs-builder/*": [ "./node_modules/@mui/monorepo/packages/api-docs-builder/*"