Skip to content

Commit

Permalink
[docs] Live demos v2 (mui#34870)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari authored and Daniel Rabe committed Nov 29, 2022
1 parent d49b658 commit bca349d
Show file tree
Hide file tree
Showing 19 changed files with 592 additions and 150 deletions.
8 changes: 4 additions & 4 deletions docs/data/material/components/app-bar/app-bar-pt.md
Expand Up @@ -36,7 +36,7 @@ Uma barra de pesquisa lateral

## Responsive App bar with Drawer

{{"demo": "DrawerAppBar.js", "bg": true,"iframe": true}}
{{"demo": "DrawerAppBar.js", "bg": true, "iframe": true, "disableLiveEdit": true}}

## App bar with a primary search field

Expand Down Expand Up @@ -103,19 +103,19 @@ You can use the `useScrollTrigger()` hook to respond to user scroll actions.

The app bar hides on scroll down to leave more space for reading.

{{"demo": "HideAppBar.js", "iframe": true}}
{{"demo": "HideAppBar.js", "iframe": true, "disableLiveEdit": true}}

### Elevate App bar

The app bar elevates on scroll to communicate that the user is not at the top of the page.

{{"demo": "ElevateAppBar.js", "iframe": true}}
{{"demo": "ElevateAppBar.js", "iframe": true, "disableLiveEdit": true}}

### Voltar ao topo

A floating action buttons appears on scroll to make it easy to get back to the top of the page.

{{"demo": "BackToTop.js", "iframe": true}}
{{"demo": "BackToTop.js", "iframe": true, "disableLiveEdit": true}}

### `useScrollTrigger([options]) => trigger`

Expand Down
8 changes: 4 additions & 4 deletions docs/data/material/components/app-bar/app-bar-zh.md
Expand Up @@ -36,7 +36,7 @@ materialDesign: https://m2.material.io/components/app-bars-top

## 带有抽屉的响应式应用栏

{{"demo": "DrawerAppBar.js", "bg": true,"iframe": true}}
{{"demo": "DrawerAppBar.js", "bg": true, "iframe": true, "disableLiveEdit": true}}

## 带有主搜索输入框的应用栏

Expand Down Expand Up @@ -103,19 +103,19 @@ function App() {

向下滚动隐藏应用栏,从而为阅读提供更多空间。

{{"demo": "HideAppBar.js", "iframe": true}}
{{"demo": "HideAppBar.js", "iframe": true, "disableLiveEdit": true}}

### 提升应用栏

应用栏会在滚动时提升,以表明用户还未到页面的顶部。

{{"demo": "ElevateAppBar.js", "iframe": true}}
{{"demo": "ElevateAppBar.js", "iframe": true, "disableLiveEdit": true}}

### 回到顶部

滚动时出现一个浮动操作按钮,以便返回页面的顶部。

{{"demo": "BackToTop.js", "iframe": true}}
{{"demo": "BackToTop.js", "iframe": true, "disableLiveEdit": true}}

### `useScrollTrigger([options]) => trigger`

Expand Down
6 changes: 3 additions & 3 deletions docs/data/material/components/app-bar/app-bar.md
Expand Up @@ -103,19 +103,19 @@ You can use the `useScrollTrigger()` hook to respond to user scroll actions.

The app bar hides on scroll down to leave more space for reading.

{{"demo": "HideAppBar.js", "iframe": true}}
{{"demo": "HideAppBar.js", "iframe": true, "disableLiveEdit": true}}

### Elevate App bar

The app bar elevates on scroll to communicate that the user is not at the top of the page.

{{"demo": "ElevateAppBar.js", "iframe": true}}
{{"demo": "ElevateAppBar.js", "iframe": true, "disableLiveEdit": true}}

### Back to top

A floating action button appears on scroll to make it easy to get back to the top of the page.

{{"demo": "BackToTop.js", "iframe": true}}
{{"demo": "BackToTop.js", "iframe": true, "disableLiveEdit": true}}

### `useScrollTrigger([options]) => trigger`

Expand Down
4 changes: 2 additions & 2 deletions docs/data/material/components/drawers/drawers-pt.md
Expand Up @@ -50,7 +50,7 @@ Você pode configurar a propriedade `SwipeableDrawer` para visualizar uma borda

Se você estiver em uma área de trabalho, poderá alternar o drawer com o botão "OPEN". Se estiver pelo celular, abra a demonstração no CodeSandbox (ícone "editar") e deslizar.

{{"demo": "SwipeableEdgeDrawer.js", "iframe": true, "height": 400, "maxWidth": 300}}
{{"demo": "SwipeableEdgeDrawer.js", "iframe": true, "disableLiveEdit": true, "height": 400, "maxWidth": 300}}

### Navegação em altura total

Expand All @@ -71,7 +71,7 @@ More details in the [Modal performance section](/material-ui/react-modal/#perfor

You can use the `temporary` variant to display a drawer for small screens and `permanent` for a drawer for wider screens.

{{"demo": "ResponsiveDrawer.js", "iframe": true}}
{{"demo": "ResponsiveDrawer.js", "iframe": true, "disableLiveEdit": true}}

## Drawer persistente

Expand Down
4 changes: 2 additions & 2 deletions docs/data/material/components/drawers/drawers-zh.md
Expand Up @@ -50,7 +50,7 @@ const iOS =

如果你使用的是桌面设备,那么可以点击 "OPEN" 按钮来切换抽屉的显示。 如果你使用的设备是手机,那么可以在 CodeSandbox(“编辑”图标)中打开该演示,并尝试滑动抽屉。

{{"demo": "SwipeableEdgeDrawer.js", "iframe": true, "height": 400, "maxWidth": 300}}
{{"demo": "SwipeableEdgeDrawer.js", "iframe": true, "disableLiveEdit": true, "height": 400, "maxWidth": 300}}

### 全高导航栏

Expand All @@ -71,7 +71,7 @@ More details in the [Modal performance section](/material-ui/react-modal/#perfor

You can use the `temporary` variant to display a drawer for small screens and `permanent` for a drawer for wider screens.

{{"demo": "ResponsiveDrawer.js", "iframe": true}}
{{"demo": "ResponsiveDrawer.js", "iframe": true, "disableLiveEdit": true}}

## 持久的抽屉

Expand Down
4 changes: 2 additions & 2 deletions docs/data/material/components/drawers/drawers.md
Expand Up @@ -57,7 +57,7 @@ You can configure the `SwipeableDrawer` to have a visible edge when closed.
If you are on a desktop, you can toggle the drawer with the "OPEN" button.
If you are on mobile, you can open the demo in CodeSandbox ("edit" icon) and swipe.

{{"demo": "SwipeableEdgeDrawer.js", "iframe": true, "height": 400, "maxWidth": 300}}
{{"demo": "SwipeableEdgeDrawer.js", "iframe": true, "disableLiveEdit": true, "height": 400, "maxWidth": 300}}

### Keep mounted

Expand All @@ -78,7 +78,7 @@ More details in the [Modal performance section](/material-ui/react-modal/#perfor

You can use the `temporary` variant to display a drawer for small screens and `permanent` for a drawer for wider screens.

{{"demo": "ResponsiveDrawer.js", "iframe": true}}
{{"demo": "ResponsiveDrawer.js", "iframe": true, "disableLiveEdit": true}}

## Persistent drawer

Expand Down
2 changes: 2 additions & 0 deletions docs/package.json
Expand Up @@ -106,6 +106,8 @@
"react-is": "^18.2.0",
"react-number-format": "^4.9.4",
"react-router-dom": "^6.4.2",
"react-runner": "^1.0.3",
"react-simple-code-editor": "^0.13.1",
"react-spring": "^8.0.27",
"react-swipeable-views": "^0.14.0",
"react-transition-group": "^4.4.5",
Expand Down
7 changes: 7 additions & 0 deletions docs/packages/markdown/extractImports.js
@@ -0,0 +1,7 @@
const importModuleRegexp = /^import [^'"]* from ['"]([^'"\n ][^'"\n ]*)['"]/gm;

function extractImports(code) {
return (code.match(importModuleRegexp) || []).map((x) => x.replace(importModuleRegexp, '$1'));
}

module.exports = extractImports;
25 changes: 24 additions & 1 deletion docs/packages/markdown/loader.js
@@ -1,6 +1,7 @@
const { promises: fs, readdirSync } = require('fs');
const path = require('path');
const { prepareMarkdown } = require('./parseMarkdown');
const extractImports = require('./extractImports');

const notEnglishMarkdownRegExp = /-([a-z]{2})\.md$/;
// TODO: pass as argument
Expand Down Expand Up @@ -123,6 +124,7 @@ module.exports = async function demoLoader() {
const { docs } = prepareMarkdown({ pageFilename, translations, componentPackageMapping });

const demos = {};
const importedModuleIDs = new Set();
const components = {};
const demoModuleIDs = new Set();
const componentModuleIDs = new Set();
Expand Down Expand Up @@ -158,6 +160,9 @@ module.exports = async function demoLoader() {
raw: await fs.readFile(moduleFilepath, { encoding: 'utf8' }),
};
demoModuleIDs.add(moduleID);
extractImports(demos[demoName].raw).forEach((importModuleID) =>
importedModuleIDs.add(importModuleID),
);

try {
const previewFilepath = moduleFilepath.replace(/\.js$/, '.tsx.preview');
Expand Down Expand Up @@ -212,6 +217,14 @@ module.exports = async function demoLoader() {
});

const transformed = `
${Array.from(importedModuleIDs)
.map((moduleID) => {
return `import * as ${moduleIDToJSIdentifier(
moduleID.replace('@', '$'),
)} from '${moduleID}';`;
})
.join('\n')}
${Array.from(demoModuleIDs)
.map((moduleID) => {
return `import ${moduleIDToJSIdentifier(moduleID)} from '${moduleID}';`;
Expand All @@ -224,6 +237,16 @@ module.exports = async function demoLoader() {
.join('\n')}
export const docs = ${JSON.stringify(docs, null, 2)};
export const demos = ${JSON.stringify(demos, null, 2)};
demos.scope = {
process: {},
import: {
${Array.from(importedModuleIDs)
.map((moduleID) => ` "${moduleID}": ${moduleIDToJSIdentifier(moduleID.replace('@', '$'))},`)
.join('\n')}
},
};
export const demoComponents = {
${Array.from(demoModuleIDs)
.map((moduleID) => {
Expand All @@ -238,7 +261,7 @@ ${Array.from(componentModuleIDs)
})
.join('\n')}
};
`;
`;

return transformed;
};
46 changes: 46 additions & 0 deletions docs/src/modules/components/CodeCopyButton.tsx
@@ -0,0 +1,46 @@
import * as React from 'react';
import copy from 'clipboard-copy';

interface CodeCopyButtonProps {
code: string;
}

export default function CodeCopyButton(props: CodeCopyButtonProps) {
const { code, ...other } = props;
const [copied, setCopied] = React.useState(false);
// This component is designed to be wrapped in NoSsr
const macOS = window.navigator.platform.toUpperCase().indexOf('MAC') >= 0;
const key = macOS ? '⌘' : 'Ctrl + ';

React.useEffect(() => {
if (copied) {
const timeout = setTimeout(() => {
setCopied(false);
}, 2000);
return () => {
clearTimeout(timeout);
};
}
return undefined;
}, [copied]);

return (
<button
{...other}
aria-label="Copy the code"
type="button"
className="MuiCode-copy"
onClick={async (event) => {
event.stopPropagation();
setCopied(true);
await copy(code);
}}
>
{/* material-ui/no-hardcoded-labels */}
{copied ? 'Copied' : 'Copy'}&nbsp;
<span className="MuiCode-copyKeypress">
<span>(or</span> {key}C<span>)</span>
</span>
</button>
);
}

0 comments on commit bca349d

Please sign in to comment.