diff --git a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx index 6ddc80f67dc3..4f4bb6c3b1ac 100644 --- a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx +++ b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx @@ -5,7 +5,7 @@ import stackblitzSdk from '@stackblitz/sdk'; import { Alert, Badge, Space, Tooltip } from 'antd'; import { createStyles, css } from 'antd-style'; import classNames from 'classnames'; -import { FormattedMessage, useSiteData } from 'dumi'; +import { FormattedMessage, useSiteData, LiveContext } from 'dumi'; import LZString from 'lz-string'; import type { AntdPreviewerProps } from './Previewer'; @@ -21,6 +21,7 @@ import RiddleIcon from '../../common/RiddleIcon'; import type { SiteContextProps } from '../../slots/SiteContext'; import SiteContext from '../../slots/SiteContext'; import { ping } from '../../utils'; +import LiveDemo from 'dumi/theme-default/slots/LiveDemo'; const { ErrorBoundary } = Alert; @@ -107,6 +108,8 @@ const CodePreviewer: React.FC = (props) => { const { pkg } = useSiteData(); const location = useLocation(); + const { enabled: liveEnabled } = useContext(LiveContext); + const { styles } = useStyle(); const entryCode = asset.dependencies['index.tsx'].value; @@ -363,9 +366,13 @@ createRoot(document.getElementById('container')).render(); const codeBox: React.ReactNode = (
- - {liveDemo.current} - + {!liveEnabled ? ( + + {liveDemo.current} + + ) : ( + + )}
diff --git a/.dumi/theme/builtins/Previewer/Previewer.tsx b/.dumi/theme/builtins/Previewer/Previewer.tsx index fb23c55e0f71..6a1ea91b9dbc 100644 --- a/.dumi/theme/builtins/Previewer/Previewer.tsx +++ b/.dumi/theme/builtins/Previewer/Previewer.tsx @@ -1,6 +1,6 @@ import React from 'react'; import type { IPreviewerProps } from 'dumi'; -import { useTabMeta } from 'dumi'; +import { LiveProvider, useTabMeta } from 'dumi'; import CodePreviewer from './CodePreviewer'; import DesignPreviewer from './DesignPreviewer'; @@ -16,7 +16,23 @@ const Previewer: React.FC = (props) => { return ; } - return ; + const codePreviewer = ; + + if (props.live === false || props.iframe) { + return codePreviewer; + } + + return ( + type === 'FILE')[0][1] + .value + } + demoId={props.asset.id} + > + {codePreviewer} + + ); }; export default Previewer; diff --git a/.dumi/theme/common/CodePreview.tsx b/.dumi/theme/common/CodePreview.tsx index b58b4661d082..164a554018f3 100644 --- a/.dumi/theme/common/CodePreview.tsx +++ b/.dumi/theme/common/CodePreview.tsx @@ -1,9 +1,11 @@ -import React, { useEffect, useMemo } from 'react'; -import { Tabs, Typography, Button } from 'antd'; +import { Button, Tabs, Typography } from 'antd'; +import { createStyles } from 'antd-style'; +import { LiveContext } from 'dumi'; import toReactElement from 'jsonml-to-react-element'; import JsonML from 'jsonml.js/lib/utils'; import Prism from 'prismjs'; -import { createStyles } from 'antd-style'; +import React, { useContext, useEffect, useMemo } from 'react'; +import LiveCode from './LiveCode'; const useStyle = createStyles(({ token, css }) => { const { colorIcon, colorBgTextHover, antCls } = token; @@ -11,12 +13,13 @@ const useStyle = createStyles(({ token, css }) => { return { code: css` position: relative; + margin-top: -16px; `, copyButton: css` color: ${colorIcon}; position: absolute; - top: 0; + top: 16px; inset-inline-end: 16px; width: 32px; text-align: center; @@ -110,6 +113,8 @@ const CodePreview: React.FC = ({ const { styles } = useStyle(); + const { enabled: liveEnabled } = useContext(LiveContext); + const items = useMemo( () => langList.map((lang: keyof typeof LANGS) => ({ @@ -117,7 +122,11 @@ const CodePreview: React.FC = ({ key: lang, children: (
- {toReactComponent(['pre', { lang, highlighted: highlightedCodes[lang] }])} + {lang === 'tsx' && liveEnabled ? ( + + ) : ( + toReactComponent(['pre', { lang, highlighted: highlightedCodes[lang] }]) + )} @@ -132,14 +141,18 @@ const CodePreview: React.FC = ({ } if (langList.length === 1) { - return toReactComponent([ - 'pre', - { - lang: langList[0], - highlighted: highlightedCodes[langList[0] as keyof typeof LANGS], - className: 'highlight', - }, - ]); + return liveEnabled ? ( + + ) : ( + toReactComponent([ + 'pre', + { + lang: langList[0], + highlighted: highlightedCodes[langList[0] as keyof typeof LANGS], + className: 'highlight', + }, + ]) + ); } return ; diff --git a/.dumi/theme/common/LiveCode.tsx b/.dumi/theme/common/LiveCode.tsx new file mode 100644 index 000000000000..9f80e95c6e04 --- /dev/null +++ b/.dumi/theme/common/LiveCode.tsx @@ -0,0 +1,85 @@ +import type { FC } from 'react'; +import React, { useEffect, useState } from 'react'; +import { createStyles } from 'antd-style'; +import LiveEditor from '../slots/LiveEditor'; +import LiveError from '../slots/LiveError'; +import { EditFilled } from '@ant-design/icons'; +import { Tooltip } from 'antd'; +import useLocale from '../../hooks/useLocale'; + +const useStyle = createStyles(({ token, css }) => { + const { colorPrimaryBorder, colorIcon, colorPrimary } = token; + + return { + editor: css` + .npm__react-simple-code-editor__textarea { + outline: none; + + &:hover { + border: 1px solid ${colorPrimaryBorder} !important; + } + + &:focus { + border: 1px solid ${colorPrimary} !important; + } + } + `, + + editableIcon: css` + position: absolute; + height: 32px; + width: 32px; + display: flex; + align-items: center; + justify-content: center; + top: 16px; + inset-inline-end: 56px; + color: ${colorIcon}; + `, + }; +}); + +const locales = { + cn: { + demoEditable: '编辑 Demo 可实时预览', + }, + en: { + demoEditable: 'Edit demo with real-time preview', + }, +}; + +const HIDE_LIVE_DEMO_TIP = 'hide-live-demo-tip'; + +const LiveCode: FC = () => { + const [open, setOpen] = useState(false); + const { styles } = useStyle(); + const [locale] = useLocale(locales); + + useEffect(() => { + const shouldOpen = !localStorage.getItem(HIDE_LIVE_DEMO_TIP); + if (shouldOpen) { + setOpen(true); + } + }, []); + + const handleOpenChange = (newOpen: boolean) => { + setOpen(newOpen); + if (!newOpen) { + localStorage.setItem(HIDE_LIVE_DEMO_TIP, 'true'); + } + }; + + return ( + <> +
+ + +
+ + + + + ); +}; + +export default LiveCode; diff --git a/.dumi/theme/common/styles/Demo.tsx b/.dumi/theme/common/styles/Demo.tsx index 9b0d8c1faa96..e29c4797ce6c 100644 --- a/.dumi/theme/common/styles/Demo.tsx +++ b/.dumi/theme/common/styles/Demo.tsx @@ -324,7 +324,6 @@ const GlobalDemoStyles: React.FC = () => { border: none; box-shadow: unset; padding: 12px 16px; - margin-top: -16px; font-size: 13px; } } diff --git a/.dumi/theme/slots/LiveEditor/index.tsx b/.dumi/theme/slots/LiveEditor/index.tsx new file mode 100644 index 000000000000..f3f68650e9ef --- /dev/null +++ b/.dumi/theme/slots/LiveEditor/index.tsx @@ -0,0 +1,21 @@ +import type { FC } from 'react'; +import React from 'react'; +import DumiLiveEditor from 'dumi/theme-default/slots/LiveEditor'; + +const LiveEditor: FC = () => ( + +); + +export default LiveEditor; diff --git a/.dumi/theme/slots/LiveError/index.tsx b/.dumi/theme/slots/LiveError/index.tsx new file mode 100644 index 000000000000..35c5e50eeca2 --- /dev/null +++ b/.dumi/theme/slots/LiveError/index.tsx @@ -0,0 +1,15 @@ +import type { FC } from 'react'; +import React, { useContext } from 'react'; +import { LiveContext } from 'dumi'; +import { Alert, theme } from 'antd'; + +const LiveError: FC = () => { + const { error } = useContext(LiveContext); + const { token } = theme.useToken(); + + return error ? ( + + ) : null; +}; + +export default LiveError; diff --git a/.dumirc.ts b/.dumirc.ts index 16fd2d16c517..01d2a1182ef2 100644 --- a/.dumirc.ts +++ b/.dumirc.ts @@ -14,6 +14,7 @@ export default defineConfig({ ssr: process.env.NODE_ENV === 'production' ? {} : false, hash: true, mfsu: false, + live: true, crossorigin: {}, outputPath: '_site', favicons: ['https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png'], diff --git a/components/alert/index.ts b/components/alert/index.ts index 5bb8dd2dbe8a..6b3a78f121c2 100644 --- a/components/alert/index.ts +++ b/components/alert/index.ts @@ -1,3 +1,4 @@ +import type React from 'react'; import type { AlertProps } from './Alert'; import InternalAlert from './Alert'; import ErrorBoundary from './ErrorBoundary'; diff --git a/components/breadcrumb/demo/react-router.md b/components/breadcrumb/demo/react-router.md deleted file mode 100644 index e700fb2f60a5..000000000000 --- a/components/breadcrumb/demo/react-router.md +++ /dev/null @@ -1,26 +0,0 @@ -## zh-CN - -与 `react-router@6+` 结合使用,生成和路由绑定的面包屑。 - -## en-US - -Used together with `react-router@6+`. - -```css -.demo { - margin: 16px; -} -.demo-nav { - height: 30px; - margin-bottom: 16px; - line-height: 30px; - background: #f8f8f8; -} -.demo-nav a { - padding: 0 8px; - line-height: 30px; -} -.app-list { - margin-top: 16px; -} -``` diff --git a/components/breadcrumb/demo/react-router.tsx b/components/breadcrumb/demo/react-router.tsx deleted file mode 100644 index 8bd4976c85a2..000000000000 --- a/components/breadcrumb/demo/react-router.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react'; -import { HashRouter, Link, Route, Routes, useLocation } from 'react-router-dom'; -import { Alert, Breadcrumb } from 'antd'; - -const Apps = () => ( -
    -
  • - Application1:Detail -
  • -
  • - Application2:Detail -
  • -
-); - -const breadcrumbNameMap: Record = { - '/apps': 'Application List', - '/apps/1': 'Application1', - '/apps/2': 'Application2', - '/apps/1/detail': 'Detail', - '/apps/2/detail': 'Detail', -}; - -const Home = () => { - const location = useLocation(); - const pathSnippets = location.pathname.split('/').filter((i) => i); - - const extraBreadcrumbItems = pathSnippets.map((_, index) => { - const url = `/${pathSnippets.slice(0, index + 1).join('/')}`; - return { - key: url, - title: {breadcrumbNameMap[url]}, - }; - }); - - const breadcrumbItems = [ - { - title: Home, - key: 'home', - }, - ].concat(extraBreadcrumbItems); - - return ( -
-
- Home - Application List -
- - } /> - Home Page} /> - - - -
- ); -}; - -const App: React.FC = () => ( - - - -); - -export default App; diff --git a/components/breadcrumb/index.en-US.md b/components/breadcrumb/index.en-US.md index 2f6e041829b9..94e3d32372fe 100644 --- a/components/breadcrumb/index.en-US.md +++ b/components/breadcrumb/index.en-US.md @@ -37,7 +37,6 @@ return ; Basic Usage With an Icon -react-router V6 Configuring the Separator Bread crumbs with drop down menu Configuring the Separator Independently diff --git a/components/breadcrumb/index.zh-CN.md b/components/breadcrumb/index.zh-CN.md index 25754eaf0dbb..0447a56012d8 100644 --- a/components/breadcrumb/index.zh-CN.md +++ b/components/breadcrumb/index.zh-CN.md @@ -38,7 +38,6 @@ return ; 基本 带有图标的 -react-router V6 分隔符 带下拉菜单的面包屑 独立的分隔符 diff --git a/components/calendar/demo/customize-header.tsx b/components/calendar/demo/customize-header.tsx index 4b969e0f33c1..9eed3a820912 100644 --- a/components/calendar/demo/customize-header.tsx +++ b/components/calendar/demo/customize-header.tsx @@ -1,3 +1,7 @@ +/** + * live: false + */ + import React from 'react'; import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; diff --git a/components/calendar/demo/lunar.tsx b/components/calendar/demo/lunar.tsx index efc64412a0c2..95035843a2dd 100644 --- a/components/calendar/demo/lunar.tsx +++ b/components/calendar/demo/lunar.tsx @@ -1,4 +1,5 @@ -import dayjs, { type Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; +import type { Dayjs } from 'dayjs'; import React from 'react'; import { Lunar, HolidayUtil } from 'lunar-typescript'; import { createStyles } from 'antd-style'; diff --git a/components/config-provider/demo/locale.tsx b/components/config-provider/demo/locale.tsx index 61cee232ce73..f49a206221e2 100644 --- a/components/config-provider/demo/locale.tsx +++ b/components/config-provider/demo/locale.tsx @@ -1,3 +1,7 @@ +/** + * live: false + */ + import { EllipsisOutlined } from '@ant-design/icons'; import dayjs from 'dayjs'; import React, { useState } from 'react'; diff --git a/components/icon/demo/basic.tsx b/components/icon/demo/basic.tsx index 72a466efacd6..4e8c6bd2d414 100644 --- a/components/icon/demo/basic.tsx +++ b/components/icon/demo/basic.tsx @@ -1,3 +1,7 @@ +/** + * live: false + */ + import React from 'react'; import { HomeOutlined, diff --git a/package.json b/package.json index b0485ab738c7..68130c1504a4 100644 --- a/package.json +++ b/package.json @@ -218,7 +218,7 @@ "cross-fetch": "^4.0.0", "crypto": "^1.0.1", "dekko": "^0.2.1", - "dumi": "^2.3.0-alpha.7", + "dumi": "^2.3.0-alpha.9", "dumi-plugin-color-chunk": "^1.0.2", "duplicate-package-checker-webpack-plugin": "^3.0.0", "esbuild-loader": "^4.0.0",