diff --git a/docs/data/joy/getting-started/templates/TemplateCollection.js b/docs/data/joy/getting-started/templates/TemplateCollection.js index 64532dffa42ffd..c772a260b3300b 100644 --- a/docs/data/joy/getting-started/templates/TemplateCollection.js +++ b/docs/data/joy/getting-started/templates/TemplateCollection.js @@ -10,11 +10,11 @@ import Link from '@mui/joy/Link'; import List from '@mui/joy/List'; import Button from '@mui/joy/Button'; import Typography from '@mui/joy/Typography'; -import SvgIcon from '@mui/joy/SvgIcon'; import Visibility from '@mui/icons-material/Visibility'; import CodeRoundedIcon from '@mui/icons-material/CodeRounded'; -import codeSandbox from 'docs/src/modules/sandbox/CodeSandbox'; +import stackBlitz from 'docs/src/modules/sandbox/StackBlitz'; import sourceJoyTemplates from 'docs/src/modules/joy/sourceJoyTemplates'; +import SandboxIcon from 'docs/src/modules/components/SandboxIcon'; /** * To display a template on the site: @@ -269,17 +269,13 @@ export default function TemplateCollection() { variant="outlined" color="neutral" fullWidth - startDecorator={ - - - - } - aria-label="CodeSandbox playground" + startDecorator={} + aria-label="Open sandbox" data-ga-event-category="joy-template" data-ga-event-label={template.name} - data-ga-event-action="codesandbox" + data-ga-event-action="stackblitz" onClick={() => - codeSandbox + stackBlitz .createJoyTemplate({ ...item, title: `${startCase(template.name)} Template - Joy UI`, @@ -289,11 +285,11 @@ export default function TemplateCollection() { item.codeVariant === 'TS' ? 'tsx' : 'js' }`, }) - .openSandbox() + .openStackBlitz() } sx={{ fontFamily: 'IBM Plex Sans' }} > - CodeSandbox + Open sandbox diff --git a/docs/data/material/getting-started/templates/dashboard/theme/customizations/dataGrid.js b/docs/data/material/getting-started/templates/dashboard/theme/customizations/dataGrid.js index ed33816d0fc681..b98c96ea81fa7e 100644 --- a/docs/data/material/getting-started/templates/dashboard/theme/customizations/dataGrid.js +++ b/docs/data/material/getting-started/templates/dashboard/theme/customizations/dataGrid.js @@ -1,6 +1,5 @@ import { paperClasses } from '@mui/material/Paper'; import { alpha } from '@mui/material/styles'; - import { menuItemClasses } from '@mui/material/MenuItem'; import { listItemIconClasses } from '@mui/material/ListItemIcon'; import { iconButtonClasses } from '@mui/material/IconButton'; @@ -8,6 +7,7 @@ import { checkboxClasses } from '@mui/material/Checkbox'; import { listClasses } from '@mui/material/List'; import { gridClasses } from '@mui/x-data-grid'; import { tablePaginationClasses } from '@mui/material/TablePagination'; + import { gray } from '../../../shared-theme/themePrimitives'; /* eslint-disable import/prefer-default-export */ diff --git a/docs/data/material/getting-started/templates/dashboard/theme/customizations/dataGrid.ts b/docs/data/material/getting-started/templates/dashboard/theme/customizations/dataGrid.ts new file mode 100644 index 00000000000000..13e6b338f583d4 --- /dev/null +++ b/docs/data/material/getting-started/templates/dashboard/theme/customizations/dataGrid.ts @@ -0,0 +1,142 @@ +import { paperClasses } from '@mui/material/Paper'; +import { alpha } from '@mui/material/styles'; +import { menuItemClasses } from '@mui/material/MenuItem'; +import { listItemIconClasses } from '@mui/material/ListItemIcon'; +import { iconButtonClasses } from '@mui/material/IconButton'; +import { checkboxClasses } from '@mui/material/Checkbox'; +import { listClasses } from '@mui/material/List'; +import { gridClasses } from '@mui/x-data-grid'; +import { tablePaginationClasses } from '@mui/material/TablePagination'; +import type { ComponentsOverrides, ComponentsProps, Theme } from '@mui/material/styles'; + +import { gray } from '../../../shared-theme/themePrimitives'; + +interface DataGridComponents { + MuiDataGrid?: { + defaultProps?: ComponentsProps['MuiDataGrid']; + styleOverrides?: ComponentsOverrides['MuiDataGrid']; + }; +} + +/* eslint-disable import/prefer-default-export */ +export const dataGridCustomizations: DataGridComponents = { + MuiDataGrid: { + styleOverrides: { + root: ({ theme }) => ({ + '--DataGrid-overlayHeight': '300px', + overflow: 'clip', + borderColor: (theme.vars || theme).palette.divider, + backgroundColor: (theme.vars || theme).palette.background.default, + [`& .${gridClasses.columnHeader}`]: { + backgroundColor: (theme.vars || theme).palette.background.paper, + }, + [`& .${gridClasses.footerContainer}`]: { + backgroundColor: (theme.vars || theme).palette.background.paper, + }, + [`& .${checkboxClasses.root}`]: { + padding: theme.spacing(0.5), + '& > svg': { + fontSize: '1rem', + }, + }, + [`& .${tablePaginationClasses.root}`]: { + marginRight: theme.spacing(1), + '& .MuiIconButton-root': { + maxHeight: 32, + maxWidth: 32, + '& > svg': { + fontSize: '1rem', + }, + }, + }, + }), + cell: ({ theme }) => ({ + borderTopColor: (theme.vars || theme).palette.divider, + }), + menu: ({ theme }) => ({ + borderRadius: theme.shape.borderRadius, + backgroundImage: 'none', + [`& .${paperClasses.root}`]: { + border: `1px solid ${(theme.vars || theme).palette.divider}`, + }, + [`& .${menuItemClasses.root}`]: { + margin: '0 4px', + }, + [`& .${listItemIconClasses.root}`]: { + marginRight: 0, + }, + [`& .${listClasses.root}`]: { + paddingLeft: 0, + paddingRight: 0, + }, + }), + row: ({ theme }) => ({ + '&:last-of-type': { + borderBottom: `1px solid ${(theme.vars || theme).palette.divider}`, + }, + '&:hover': { + backgroundColor: (theme.vars || theme).palette.action.hover, + }, + '&.Mui-selected': { + background: (theme.vars || theme).palette.action.selected, + '&:hover': { + backgroundColor: (theme.vars || theme).palette.action.hover, + }, + }, + }), + iconButtonContainer: ({ theme }) => ({ + [`& .${iconButtonClasses.root}`]: { + border: 'none', + backgroundColor: 'transparent', + '&:hover': { + backgroundColor: alpha(theme.palette.action.selected, 0.3), + }, + '&:active': { + backgroundColor: gray[200], + }, + ...theme.applyStyles('dark', { + color: gray[50], + '&:hover': { + backgroundColor: gray[800], + }, + '&:active': { + backgroundColor: gray[900], + }, + }), + }, + }), + menuIconButton: ({ theme }) => ({ + border: 'none', + backgroundColor: 'transparent', + '&:hover': { + backgroundColor: gray[100], + }, + '&:active': { + backgroundColor: gray[200], + }, + ...theme.applyStyles('dark', { + color: gray[50], + '&:hover': { + backgroundColor: gray[800], + }, + '&:active': { + backgroundColor: gray[900], + }, + }), + }), + filterForm: ({ theme }) => ({ + gap: theme.spacing(1), + alignItems: 'flex-end', + }), + columnsManagementHeader: ({ theme }) => ({ + paddingRight: theme.spacing(3), + paddingLeft: theme.spacing(3), + }), + columnHeaderTitleContainer: { + flexGrow: 1, + justifyContent: 'space-between', + }, + columnHeaderDraggableContainer: { paddingRight: 2 }, + }, + }, +}; diff --git a/docs/src/modules/components/DemoToolbar.js b/docs/src/modules/components/DemoToolbar.js index d3c78d6f9b50e1..317ba91248553f 100644 --- a/docs/src/modules/components/DemoToolbar.js +++ b/docs/src/modules/components/DemoToolbar.js @@ -8,7 +8,6 @@ import MDButton from '@mui/material/Button'; import Box from '@mui/material/Box'; import MDToggleButton from '@mui/material/ToggleButton'; import MDToggleButtonGroup, { toggleButtonGroupClasses } from '@mui/material/ToggleButtonGroup'; -import SvgIcon from '@mui/material/SvgIcon'; import Snackbar from '@mui/material/Snackbar'; import Menu from '@mui/material/Menu'; import MDMenuItem, { menuItemClasses } from '@mui/material/MenuItem'; @@ -23,7 +22,7 @@ import { useSetCodeVariant } from 'docs/src/modules/utils/codeVariant'; import { useTranslate } from '@mui/docs/i18n'; import OpenMuiChat from 'docs/src/modules/components/OpenMuiChat'; import stylingSolutionMapping from 'docs/src/modules/utils/stylingSolutionMapping'; -import codeSandbox from '../sandbox/CodeSandbox'; +import SandboxIcon from './SandboxIcon'; import stackBlitz from '../sandbox/StackBlitz'; const Root = styled('div')(({ theme }) => [ @@ -356,7 +355,6 @@ export default function DemoToolbar(props) { React.useRef(null), React.useRef(null), React.useRef(null), - React.useRef(null), ]; // if the code is not open we hide the language controls const isFocusableControl = React.useCallback( @@ -492,36 +490,18 @@ export default function DemoToolbar(props) { {showCodeLabel} {demoOptions.hideEditButton ? null : ( - - - stackBlitz.createReactApp(demoData).openSandbox()} - {...getControlProps(4)} - sx={{ borderRadius: 1 }} - > - - - - - - - codeSandbox.createReactApp(demoData).openSandbox()} - {...getControlProps(5)} - sx={{ borderRadius: 1 }} - > - - - - - - + + stackBlitz.createReactApp(demoData).openSandbox()} + {...getControlProps(4)} + sx={{ borderRadius: 1 }} + > + + + )} {copyIcon} @@ -541,7 +521,7 @@ export default function DemoToolbar(props) { data-ga-event-label={demo.gaLabel} data-ga-event-action="reset-focus" onClick={handleResetFocusClick} - {...getControlProps(7)} + {...getControlProps(6)} sx={{ borderRadius: 1 }} > @@ -554,7 +534,7 @@ export default function DemoToolbar(props) { data-ga-event-label={demo.gaLabel} data-ga-event-action="reset" onClick={onResetDemoClick} - {...getControlProps(8)} + {...getControlProps(7)} sx={{ borderRadius: 1 }} > @@ -565,7 +545,7 @@ export default function DemoToolbar(props) { aria-label={t('seeMore')} aria-owns={anchorEl ? 'demo-menu-more' : undefined} aria-haspopup="true" - {...getControlProps(9)} + {...getControlProps(8)} sx={{ borderRadius: 1 }} > diff --git a/docs/src/modules/components/JoyThemeBuilder.tsx b/docs/src/modules/components/JoyThemeBuilder.tsx index 4b7c81a4fe1fec..00480ab7c13ac9 100644 --- a/docs/src/modules/components/JoyThemeBuilder.tsx +++ b/docs/src/modules/components/JoyThemeBuilder.tsx @@ -21,6 +21,7 @@ import Box from '@mui/joy/Box'; import Button from '@mui/joy/Button'; import Checkbox from '@mui/joy/Checkbox'; import Card from '@mui/joy/Card'; +import Tooltip from '@mui/joy/Tooltip'; import CardCover from '@mui/joy/CardCover'; import Divider from '@mui/joy/Divider'; import FormControl from '@mui/joy/FormControl'; @@ -62,12 +63,13 @@ import DarkMode from '@mui/icons-material/DarkMode'; import LightMode from '@mui/icons-material/LightMode'; import { HighlightedCode } from '@mui/docs/HighlightedCode'; import { BrandingProvider } from '@mui/docs/branding'; -import codeSandbox from 'docs/src/modules/sandbox/CodeSandbox'; +import stackBlitz from 'docs/src/modules/sandbox/StackBlitz'; import sourceJoyTemplates, { TemplateData } from 'docs/src/modules/joy/sourceJoyTemplates'; import extractTemplates from 'docs/src/modules/utils/extractTemplates'; import generateThemeAugmentation from 'docs/src/modules/joy/generateThemeAugmentation'; import literalToObject from 'docs/src/modules/joy/literalToObject'; import getMinimalJoyTemplate from 'docs/src/modules/joy/getMinimalJoyTemplate'; +import SandboxIcon from './SandboxIcon'; const tailwindColors = { slate: { @@ -1323,7 +1325,7 @@ function TemplatesDialog({ textColor="#fff" overlay onClick={() => { - codeSandbox + stackBlitz .createJoyTemplate({ ...item, files: newFiles, @@ -1331,7 +1333,7 @@ function TemplatesDialog({ title: `Joy UI - Custom theme`, codeVariant: 'TS', }) - .openSandbox(); + .openStackBlitz(); }} endDecorator={} sx={{ fontSize: 'xl', fontWeight: 'xl' }} @@ -1401,14 +1403,14 @@ function TemplatesDialog({ './result/App.tsx': getMinimalJoyTemplate(), './result/theme.ts': generateThemeCode(data), }); - codeSandbox + stackBlitz .createJoyTemplate({ ...result, codeVariant: 'TS', githubLocation: '', title: `Joy UI - Minimal template`, }) - .openSandbox(); + .openStackBlitz(); }} endDecorator={} sx={{ fontSize: 'lg', fontWeight: 'lg' }} @@ -1528,11 +1530,11 @@ export default function JoyThemeBuilder() { - - - - - + + + + + )} diff --git a/docs/src/modules/components/MaterialFreeTemplatesCollection.js b/docs/src/modules/components/MaterialFreeTemplatesCollection.js index 77f88a66c8fd4b..92c3cc9ce5bba2 100644 --- a/docs/src/modules/components/MaterialFreeTemplatesCollection.js +++ b/docs/src/modules/components/MaterialFreeTemplatesCollection.js @@ -7,15 +7,14 @@ import IconButton from '@mui/material/IconButton'; import Link from '@mui/material/Link'; import Tooltip from '@mui/material/Tooltip'; import Typography from '@mui/material/Typography'; -import SvgIcon from '@mui/material/SvgIcon'; import Visibility from '@mui/icons-material/Visibility'; import CodeRoundedIcon from '@mui/icons-material/CodeRounded'; import OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded'; import { useTranslate } from '@mui/docs/i18n'; import { pascalCase } from 'docs/src/modules/utils/helpers'; import sourceMaterialTemplates from 'docs/src/modules/material/sourceMaterialTemplates'; -import codeSandbox from 'docs/src/modules/sandbox/CodeSandbox'; import stackBlitz from 'docs/src/modules/sandbox/StackBlitz'; +import SandboxIcon from './SandboxIcon'; const sourcePrefix = `${process.env.SOURCE_CODE_REPO}/tree/v${process.env.LIB_VERSION}`; @@ -179,11 +178,11 @@ export default function MaterialFreeTemplatesCollection() { gap: 1, }} > - + - - - - - - - - codeSandbox - .createMaterialTemplate({ - ...item, - files: { ...item.files, ...materialTemplates.sharedTheme?.files }, - title: `${templateName} Template - Material UI`, - githubLocation: `${process.env.SOURCE_CODE_REPO}/blob/v${ - process.env.LIB_VERSION - }/docs/data/material/templates/${templateId}/${templateName}.${ - item.codeVariant === 'TS' ? 'tsx' : 'js' - }`, - }) - .replaceContent((content) => { - if (typeof content === 'string') { - return content - .replace(/\.\.\/shared-theme\//g, './theme/') - .replace('./App', `./${templateName}`); - } - return content; - }) - .openSandbox(`/${templateName}`) - } - > - - - + diff --git a/docs/src/modules/components/SandboxIcon.ts b/docs/src/modules/components/SandboxIcon.ts new file mode 100644 index 00000000000000..3c0cce0b49fd9f --- /dev/null +++ b/docs/src/modules/components/SandboxIcon.ts @@ -0,0 +1 @@ +export { default } from '@mui/icons-material/Launch'; diff --git a/docs/src/modules/components/TemplateFrame.js b/docs/src/modules/components/TemplateFrame.js index e80048af50e3f2..17de0c251fc80d 100644 --- a/docs/src/modules/components/TemplateFrame.js +++ b/docs/src/modules/components/TemplateFrame.js @@ -16,15 +16,14 @@ import Box from '@mui/material/Box'; import Select from '@mui/material/Select'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; -import SvgIcon from '@mui/material/SvgIcon'; import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded'; import LightModeIcon from '@mui/icons-material/LightModeOutlined'; import DarkModeIcon from '@mui/icons-material/DarkModeOutlined'; import PaletteIcon from '@mui/icons-material/PaletteOutlined'; -import codeSandbox from 'docs/src/modules/sandbox/CodeSandbox'; import stackBlitz from 'docs/src/modules/sandbox/StackBlitz'; import sourceMaterialTemplates from 'docs/src/modules/material/sourceMaterialTemplates'; import { pascalCase } from 'docs/src/modules/utils/helpers'; +import SandboxIcon from './SandboxIcon'; const StyledAppBar = styled(AppBar)(({ theme }) => ({ position: 'relative', @@ -272,12 +271,12 @@ export default function TemplateFrame({ children }) { '& > *': { flexShrink: 0 }, }} > - + - - - - - - - - codeSandbox - .createMaterialTemplate({ - ...item, - files: { ...item.files, ...materialTemplates.sharedTheme?.files }, - title: `${templateName} Template - Material UI`, - githubLocation: `${process.env.SOURCE_CODE_REPO}/blob/v${ - process.env.LIB_VERSION - }/docs/data/material/templates/${templateId}/${templateName}.${ - item.codeVariant === 'TS' ? 'tsx' : 'js' - }`, - }) - .replaceContent((content) => { - if (typeof content === 'string') { - return content - .replace(/\.\.\/shared-theme\//g, './theme/') - .replace('./App', `./${templateName}`); - } - return content; - }) - .openSandbox(`/${templateName}`) - } - sx={{ alignSelf: 'center', borderRadius: 1 }} - > - - - + diff --git a/docs/src/modules/sandbox/CodeSandbox.test.js b/docs/src/modules/sandbox/CodeSandbox.test.js deleted file mode 100644 index d81146413d57f3..00000000000000 --- a/docs/src/modules/sandbox/CodeSandbox.test.js +++ /dev/null @@ -1,267 +0,0 @@ -import { expect } from 'chai'; -import CodeSandbox from './CodeSandbox'; - -const testCase = `import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import Button from '@mui/material/Button'; - -export default function BasicButtons() { - return ( - - - - - - ); -} -`; - -describe('CodeSandbox', () => { - it('generate the correct JavaScript result', () => { - const result = CodeSandbox.createReactApp({ - title: 'BasicButtons Material Demo', - githubLocation: - 'https://github.com/mui/material-ui/blob/v5.7.0/docs/data/material/components/buttons/BasicButtons.js', - codeVariant: 'JS', - language: 'en', - raw: testCase, - }); - expect(result.files).to.deep.equal({ - 'package.json': { - content: { - private: true, - description: - 'https://github.com/mui/material-ui/blob/v5.7.0/docs/data/material/components/buttons/BasicButtons.js', - dependencies: { - react: 'latest', - // #npm-tag-reference - '@mui/material': 'latest', - 'react-dom': 'latest', - '@emotion/react': 'latest', - '@emotion/styled': 'latest', - }, - devDependencies: { - 'react-scripts': 'latest', - }, - scripts: { - start: 'react-scripts start', - build: 'react-scripts build', - test: 'react-scripts test', - eject: 'react-scripts eject', - }, - }, - }, - 'public/index.html': { - content: ` - - - - BasicButtons Material Demo - - - - - - - - - -
- \n -`, - }, - 'src/Demo.js': { - content: `import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import Button from '@mui/material/Button'; - -export default function BasicButtons() { - return ( - - - - - - ); -} -`, - }, - 'src/index.js': { - content: `import * as React from 'react'; -import * as ReactDOM from 'react-dom/client'; -import { StyledEngineProvider } from '@mui/material/styles'; -import Demo from './Demo'; - -ReactDOM.createRoot(document.querySelector("#root")).render( - - - - - -);`, - }, - }); - }); - - it('generate the correct TypeScript result', () => { - const result = CodeSandbox.createReactApp({ - title: 'BasicButtons Material Demo', - githubLocation: - 'https://github.com/mui/material-ui/blob/v5.7.0/docs/data/material/components/buttons/BasicButtons.tsx', - codeVariant: 'TS', - language: 'en', - raw: testCase, - }); - expect(result.files).to.deep.equal({ - 'package.json': { - content: { - private: true, - description: - 'https://github.com/mui/material-ui/blob/v5.7.0/docs/data/material/components/buttons/BasicButtons.tsx', - dependencies: { - react: 'latest', - // #npm-tag-reference - '@mui/material': 'latest', - 'react-dom': 'latest', - '@emotion/react': 'latest', - '@emotion/styled': 'latest', - typescript: 'latest', - }, - devDependencies: { - 'react-scripts': 'latest', - '@types/react': 'latest', - '@types/react-dom': 'latest', - }, - scripts: { - build: 'react-scripts build', - eject: 'react-scripts eject', - start: 'react-scripts start', - test: 'react-scripts test', - }, - }, - }, - 'public/index.html': { - content: ` - - - - BasicButtons Material Demo - - - - - - - - - -
- \n -`, - }, - 'src/Demo.tsx': { - content: `import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import Button from '@mui/material/Button'; - -export default function BasicButtons() { - return ( - - - - - - ); -} -`, - }, - 'src/index.tsx': { - content: `import * as React from 'react'; -import * as ReactDOM from 'react-dom/client'; -import { StyledEngineProvider } from '@mui/material/styles'; -import Demo from './Demo'; - -ReactDOM.createRoot(document.querySelector("#root")!).render( - - - - - -);`, - }, - 'tsconfig.json': { - content: `{ - "compilerOptions": { - "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react" - }, - "include": [ - "src" - ] -} -`, - }, - }); - expect(result.dependencies).to.deep.equal({ - '@emotion/react': 'latest', - '@emotion/styled': 'latest', - // #npm-tag-reference - '@mui/material': 'latest', - react: 'latest', - 'react-dom': 'latest', - typescript: 'latest', - }); - expect(result.devDependencies).to.deep.equal({ - 'react-scripts': 'latest', - '@types/react': 'latest', - '@types/react-dom': 'latest', - }); - }); - - it('should generate the correct stylesheet font link in index.html for Material Two Tones icons', () => { - const raw = `import * as React from 'react'; - import Icon from '@mui/material/Icon'; - - export default function TwoToneIcons() { - return add_circle; - } - `; - - const result = CodeSandbox.createReactApp({ - raw, - codeVariant: 'JS', - }); - - expect(result.files['public/index.html'].content).to.contain( - 'https://fonts.googleapis.com/icon?family=Material+Icons+Two+Tone', - ); - }); -}); diff --git a/docs/src/modules/sandbox/CodeSandbox.ts b/docs/src/modules/sandbox/CodeSandbox.ts deleted file mode 100644 index 0aa582a07b2a9b..00000000000000 --- a/docs/src/modules/sandbox/CodeSandbox.ts +++ /dev/null @@ -1,294 +0,0 @@ -// @ts-ignore -import LZString from 'lz-string'; -import addHiddenInput from 'docs/src/modules/utils/addHiddenInput'; -import SandboxDependencies from 'docs/src/modules/sandbox/Dependencies'; -import * as CRA from 'docs/src/modules/sandbox/CreateReactApp'; -import getFileExtension from 'docs/src/modules/sandbox/FileExtension'; -import flattenRelativeImports from 'docs/src/modules/sandbox/FlattenRelativeImports'; -import { DemoData, CodeVariant } from 'docs/src/modules/sandbox/types'; - -const CSB_DEV_DEPENDENCIES = { - 'react-scripts': 'latest', -}; - -function compress(object: any) { - return LZString.compressToBase64(JSON.stringify(object)) - .replace(/\+/g, '-') // Convert '+' to '-' - .replace(/\//g, '_') // Convert '/' to '_' - .replace(/=+$/, ''); // Remove ending '=' -} - -function openSandbox({ files, codeVariant, initialFile }: any) { - const extension = codeVariant === 'TS' ? '.tsx' : '.js'; - const parameters = compress({ files }); - - // ref: https://codesandbox.io/docs/api/#define-api - const form = document.createElement('form'); - form.method = 'POST'; - form.target = '_blank'; - form.action = 'https://codesandbox.io/api/v1/sandboxes/define'; - addHiddenInput(form, 'parameters', parameters); - addHiddenInput(form, 'embed', '1'); - addHiddenInput( - form, - 'query', - `module=${initialFile}${initialFile.match(/(\.tsx|\.ts|\.js)$/) ? '' : extension}&fontsize=12`, - ); - document.body.appendChild(form); - form.submit(); - document.body.removeChild(form); -} - -function createReactApp(demoData: DemoData) { - const ext = getFileExtension(demoData.codeVariant); - const { title, githubLocation: description } = demoData; - - const files: Record = { - 'public/index.html': { - content: CRA.getHtml(demoData), - }, - [`src/index.${ext}`]: { - content: CRA.getRootIndex(demoData), - }, - [`src/Demo.${ext}`]: { - content: flattenRelativeImports(demoData.raw), - }, - // Spread the relative modules - ...(demoData.relativeModules && - // Transform the relative modules array into an object - demoData.relativeModules.reduce( - (acc, curr) => ({ - ...acc, - // Remove the path and keep the filename - [`src/${curr.module.replace(/^.*[\\/]/g, '')}`]: { - content: flattenRelativeImports(curr.raw), - }, - }), - {}, - )), - ...(demoData.codeVariant === 'TS' && { - 'tsconfig.json': { - content: CRA.getTsconfig(), - }, - }), - }; - - const { dependencies, devDependencies } = SandboxDependencies(demoData, { - commitRef: process.env.PULL_REQUEST_ID ? process.env.COMMIT_REF : undefined, - devDeps: CSB_DEV_DEPENDENCIES, - }); - - files['package.json'] = { - content: { - private: true, - description, - dependencies, - devDependencies, - scripts: { - start: 'react-scripts start', - build: 'react-scripts build', - test: 'react-scripts test', - eject: 'react-scripts eject', - }, - }, - }; - - return { - title, - description, - files, - dependencies, - devDependencies, - /** - * @param {string} initialFile - * @description should start with `/`, for example `/Demo.tsx`. If the extension is not provided, - * it will be appended based on the code variant. - */ - openSandbox: (initialFile: string = `/src/Demo.${ext}`) => - openSandbox({ files, codeVariant: demoData.codeVariant, initialFile }), - }; -} - -function createJoyTemplate(templateData: { - title: string; - files: Record; - githubLocation: string; - codeVariant: CodeVariant; -}) { - const ext = getFileExtension(templateData.codeVariant); - const { title, githubLocation: description } = templateData; - - // document.querySelector returns 'Element | null' but createRoot expects 'Element | DocumentFragment'. - const type = templateData.codeVariant === 'TS' ? '!' : ''; - - const files: Record = { - 'public/index.html': { - content: CRA.getHtml({ - title: templateData.title, - language: 'en', - }), - }, - [`index.${ext}`]: { - content: `import * as React from 'react'; -import * as ReactDOM from 'react-dom/client'; -import { StyledEngineProvider } from '@mui/joy/styles'; -import App from './App'; - -ReactDOM.createRoot(document.querySelector("#root")${type}).render( - - - - - -);`, - }, - ...Object.entries(templateData.files).reduce( - (prev, curr) => ({ - ...prev, - [curr[0]]: { - content: curr[1], - }, - }), - {}, - ), - ...(templateData.codeVariant === 'TS' && { - 'tsconfig.json': { - content: CRA.getTsconfig(), - }, - }), - }; - - const { dependencies, devDependencies } = SandboxDependencies( - { - codeVariant: templateData.codeVariant, - raw: Object.entries(templateData.files).reduce((prev, curr) => `${prev}\n${curr}`, ''), - productId: 'joy-ui', - }, - { - commitRef: process.env.PULL_REQUEST_ID ? process.env.COMMIT_REF : undefined, - devDeps: CSB_DEV_DEPENDENCIES, - }, - ); - - files['package.json'] = { - content: { - private: true, - description, - dependencies, - devDependencies, - scripts: { - start: 'react-scripts start', - build: 'react-scripts build', - test: 'react-scripts test', - eject: 'react-scripts eject', - }, - }, - }; - - return { - title, - files, - dependencies, - devDependencies, - openSandbox: (initialFile: string = '/App') => - openSandbox({ files, codeVariant: templateData.codeVariant, initialFile }), - }; -} - -function createMaterialTemplate(templateData: { - title: string; - files: Record; - githubLocation: string; - codeVariant: CodeVariant; -}) { - const ext = getFileExtension(templateData.codeVariant); - const { title, githubLocation: description } = templateData; - - // document.querySelector returns 'Element | null' but createRoot expects 'Element | DocumentFragment'. - const type = templateData.codeVariant === 'TS' ? '!' : ''; - - const files: Record }> = { - 'public/index.html': { - content: CRA.getHtml({ - title: templateData.title, - language: 'en', - }), - }, - [`index.${ext}`]: { - content: `import * as React from 'react'; -import * as ReactDOM from 'react-dom/client'; -import { StyledEngineProvider } from '@mui/material/styles'; -import App from './App'; - -ReactDOM.createRoot(document.querySelector("#root")${type}).render( - - - - - -);`, - }, - ...Object.entries(templateData.files).reduce( - (prev, curr) => ({ - ...prev, - [curr[0]]: { - content: curr[1], - }, - }), - {}, - ), - ...(templateData.codeVariant === 'TS' && { - 'tsconfig.json': { - content: CRA.getTsconfig(), - }, - }), - }; - - const { dependencies, devDependencies } = SandboxDependencies( - { - codeVariant: templateData.codeVariant, - raw: Object.entries(templateData.files).reduce((prev, curr) => `${prev}\n${curr}`, ''), - productId: 'material-ui', - }, - { - commitRef: process.env.PULL_REQUEST_ID ? process.env.COMMIT_REF : undefined, - devDeps: CSB_DEV_DEPENDENCIES, - }, - ); - - files['package.json'] = { - content: { - private: true, - description, - dependencies, - devDependencies, - scripts: { - start: 'react-scripts start', - build: 'react-scripts build', - test: 'react-scripts test', - eject: 'react-scripts eject', - }, - }, - }; - - return { - title, - files, - dependencies, - devDependencies, - replaceContent(updater: (content: string | Record, filePath: string) => string) { - Object.keys(files).forEach((filePath) => { - files[filePath].content = updater(files[filePath].content, filePath); - }); - return this; - }, - openSandbox: (initialFile: string = '/App') => - openSandbox({ files, codeVariant: templateData.codeVariant, initialFile }), - }; -} - -export default { - createReactApp, - createJoyTemplate, - createMaterialTemplate, -}; diff --git a/docs/src/modules/sandbox/Dependencies.test.js b/docs/src/modules/sandbox/Dependencies.test.js index 00a4100cdba248..28a56383038767 100644 --- a/docs/src/modules/sandbox/Dependencies.test.js +++ b/docs/src/modules/sandbox/Dependencies.test.js @@ -267,8 +267,7 @@ import * as Utils from '@mui/utils'; 'https://pkg.pr.new/mui/material-ui/@mui/system@2d0e8b4daf20b7494c818b6f8c4cc8423bc99d6f', '@mui/utils': 'https://pkg.pr.new/mui/material-ui/@mui/utils@2d0e8b4daf20b7494c818b6f8c4cc8423bc99d6f', - '@mui/base': - 'https://pkg.pr.new/mui/material-ui/@mui/base@2d0e8b4daf20b7494c818b6f8c4cc8423bc99d6f', + '@mui/base': 'latest', }); }); diff --git a/docs/src/modules/sandbox/Dependencies.ts b/docs/src/modules/sandbox/Dependencies.ts index e3b76448c9520a..49860618a596ce 100644 --- a/docs/src/modules/sandbox/Dependencies.ts +++ b/docs/src/modules/sandbox/Dependencies.ts @@ -50,13 +50,13 @@ export default function SandboxDependencies( * @return string - A valid version for a dependency entry in a package.json */ function getMuiPackageVersion(packageName: string): string { + if (packageName === 'joy' || packageName === 'base') { + return 'latest'; + } if ( commitRef === undefined || process.env.SOURCE_CODE_REPO !== 'https://github.com/mui/material-ui' ) { - if (['joy', 'base'].includes(packageName)) { - return 'latest'; - } // #npm-tag-reference return 'latest'; }