Skip to content

Commit

Permalink
✨ feat: 主题包支持配置 ApiHeader,为组件增加头部引导
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Feb 14, 2023
1 parent 3953a3b commit 53d8aaf
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 97 deletions.
134 changes: 77 additions & 57 deletions src/components/ApiHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,96 @@
import { EditOutlined, GithubFilled } from '@ant-design/icons';
import { Typography } from 'antd';
import { Divider, Space, Typography } from 'antd';
import { useResponsive } from 'antd-style';
import { FC, memo } from 'react';
import { FC, memo, ReactNode } from 'react';
import { Flexbox } from 'react-layout-kit';

import Code from '../CodeSnippet';
import NpmFilled from './NpmFilled';

import { useSiteStore } from '../../store/useSiteStore';
import { Label, useStyles } from './style';

interface ApiTitleProps {
title: string;
componentName: string;
description?: string;
pkg: string;
sourceUrl?: string;
docsUrl?: string;
}

export const ApiHeader: FC<ApiTitleProps> = memo(({ title, description }) => {
const { styles } = useStyles();
const { mobile } = useResponsive();
interface Item {
label: string;
icon: ReactNode;
children: string;
url: string;
}

const REPO_BASE = useSiteStore((s) => s.siteData.themeConfig.repoUrl);
export const ApiHeader: FC<ApiTitleProps> = memo(
({ title, componentName, description, pkg, sourceUrl, docsUrl }) => {
const { styles } = useStyles();
const { mobile } = useResponsive();

const items = [
{
label: '源码',
icon: <GithubFilled />,
children: '查看源码',
url: `${REPO_BASE}/tree/master/src/${title}`,
},
{
label: '文档',
icon: <EditOutlined />,
children: '编辑文档',
url: `${REPO_BASE}/tree/master/docs/api/${title}`,
},
{
label: '产物',
icon: <NpmFilled />,
children: 'antd-style',
url: 'https://www.npmjs.com/package/antd-style?activeTab=explore',
},
];
const items = [
sourceUrl && {
label: '源码',
icon: <GithubFilled />,
children: '查看源码',
url: sourceUrl,
},
docsUrl && {
label: '文档',
icon: <EditOutlined />,
children: '编辑文档',
url: docsUrl,
},
{
label: '产物',
icon: <NpmFilled />,
children: pkg,
url: `https://www.npmjs.com/package/${pkg}?activeTab=explore`,
},
].filter((i) => i) as Item[];

return (
<Flexbox>
<Typography.Title className={styles.title}>{title}</Typography.Title>
{description && (
<div>
<Typography.Text type={'secondary'} className={styles.desc}>
{description}
</Typography.Text>
</div>
)}
<Flexbox style={{ marginTop: 24 }} gap={mobile ? 16 : 12}>
<Flexbox horizontal={!mobile} gap={mobile ? 12 : 0}>
<Label type={'secondary'}>引入方法</Label>
<Code>{`import { ${title} } from "antd-style";`}</Code>
</Flexbox>
{items.map((item) => (
<Flexbox horizontal key={item.label}>
<Label type={'secondary'}>{item.label}</Label>
{
<a href={item.url} target={'_blank'} rel="noreferrer">
<Flexbox horizontal align={'center'} gap={8} className={styles.text}>
<>{item.icon}</>
<>{item.children}</>
</Flexbox>
</a>
}
return (
<Flexbox>
<Typography.Title className={styles.title}>{title}</Typography.Title>
{description && (
<div>
<Typography.Text type={'secondary'} className={styles.desc}>
{description}
</Typography.Text>
</div>
)}
<Flexbox style={{ marginTop: 24 }} gap={mobile ? 16 : 24}>
<Flexbox horizontal={!mobile} gap={mobile ? 12 : 0}>
<Label type={'secondary'} style={{ display: 'flex', alignItems: 'center' }}>
引入方法
</Label>
<Code>{`import { ${componentName} } from "${pkg}";`}</Code>
</Flexbox>
))}
<Divider dashed style={{ margin: '2px 0' }} />
<Space
direction={mobile ? 'vertical' : 'horizontal'}
split={mobile ? undefined : <Divider type={'vertical'} />}
size={24}
className={styles.meta}
>
{items.map((item) => (
<Space size={24} key={item.label}>
<Label type={'secondary'}>{item.label}</Label>
{
<a href={item.url} target={'_blank'} rel="noreferrer">
<Flexbox horizontal align={'center'} gap={8} className={styles.text}>
<>{item.icon}</>
<>{item.children}</>
</Flexbox>
</a>
}
</Space>
))}
</Space>
</Flexbox>
</Flexbox>
</Flexbox>
);
});
);
},
);
3 changes: 2 additions & 1 deletion src/components/ApiHeader/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Typography } from 'antd';
import { createStyles, styled } from 'antd-style';

export const Label = styled(Typography.Text)`
width: 100px;
width: 80px;
` as any;

export const useStyles = createStyles(({ css, token, responsive: r, stylish }) => ({
Expand All @@ -20,4 +20,5 @@ export const useStyles = createStyles(({ css, token, responsive: r, stylish }) =
text: css`
${stylish.clickableText}
`,
meta: css``,
}));
18 changes: 16 additions & 2 deletions src/components/CodeSnippet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { useResponsive } from 'antd-style';
import copy from 'copy-to-clipboard';
import { FC } from 'react';

import { Prism as Highlighter } from '../Highlighter';
import { Highlighter } from '../Highlighter';

import { vs, vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import { useCopied } from '../../hooks/useCopied';
import { useStyles } from './style';

Expand Down Expand Up @@ -34,7 +35,20 @@ const CodeSnippet: FC<{ children: string }> = ({ children }) => {
setCopied();
}}
>
<Highlighter language={'javaScript'}>{children}</Highlighter>
<Highlighter
background={false}
type={'prism'}
copyable={false}
syntaxThemes={{
prism: {
dark: vscDarkPlus,
light: vs,
},
}}
language={'js'}
>
{children}
</Highlighter>
</div>
</Tooltip>
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/CodeSnippet/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ export const useStyles = createStyles(
}
pre {
background: none !important;
padding: 0 !important;
padding: 2px 8px !important;
margin: 0;
}
code[class*='language-'] {
background: none;
background: none !important;
}
`,
);
File renamed without changes.
17 changes: 15 additions & 2 deletions src/components/Highlighter/Prism.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,30 @@ Object.entries(languageMap).forEach(([key, value]) => {
SyntaxHighlighter.registerLanguage(key, value);
});

export interface PrismSyntaxTheme {
dark: { [key: string]: React.CSSProperties };
light: { [key: string]: React.CSSProperties };
}
export interface HighlighterProps {
children: string;
language: string;
theme?: Partial<PrismSyntaxTheme>;
}

export const Prism = memo<HighlighterProps>(({ children, language }) => {
const defaultTheme: PrismSyntaxTheme = {
dark: oneDark,
light: oneLight,
};

export const Prism = memo<HighlighterProps>(({ children, language, theme }) => {
const { isDarkMode, lineHeight } = useTheme();

const Theme = { ...defaultTheme, ...theme };

return (
<SyntaxHighlighter
language={language}
style={isDarkMode ? oneDark : oneLight}
style={isDarkMode ? Theme.dark : Theme.light}
customStyle={{ borderRadius: 8, lineHeight: lineHeight }}
>
{children}
Expand Down
63 changes: 38 additions & 25 deletions src/components/Highlighter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Button, ConfigProvider, Tooltip } from 'antd';
import copy from 'copy-to-clipboard';
import { CSSProperties, FC, memo } from 'react';

import { PrismSyntaxTheme } from 'dumi-theme-antd-style/components/Highlighter/Prism';
import { ShikiSyntaxTheme } from 'dumi-theme-antd-style/components/Highlighter/useShiki';
import { useCopied } from '../../hooks/useCopied';
import SyntaxHighlighter from './Highlighter';
Expand Down Expand Up @@ -32,7 +33,12 @@ export interface HighlighterProps {
style?: CSSProperties;
syntaxThemes?: {
shiki?: Partial<ShikiSyntaxTheme>;
prism?: Partial<PrismSyntaxTheme>;
};
/**
* 是否可拷贝
*/
copyable?: boolean;
}

export const Highlighter: FC<HighlighterProps> = memo(
Expand All @@ -45,6 +51,7 @@ export const Highlighter: FC<HighlighterProps> = memo(
style,
trim = true,
syntaxThemes,
copyable = true,
}) => {
const { copied, setCopied } = useCopied();
const { styles, theme, cx } = useStyles();
Expand All @@ -57,32 +64,38 @@ export const Highlighter: FC<HighlighterProps> = memo(
className={container}
style={style}
>
<ConfigProvider theme={{ token: { colorBgContainer: theme.colorBgElevated } }}>
<Tooltip
placement={'left'}
arrow={false}
title={
copied ? (
<>
<CheckOutlined style={{ color: theme.colorSuccess }} /> 复制成功
</>
) : (
'复制'
)
}
>
<Button
icon={<CopyOutlined />}
className={styles.button}
onClick={() => {
copy(children);
setCopied();
}}
/>
</Tooltip>
</ConfigProvider>
{copyable && (
<ConfigProvider theme={{ token: { colorBgContainer: theme.colorBgElevated } }}>
<Tooltip
placement={'left'}
arrow={false}
title={
copied ? (
<>
<CheckOutlined style={{ color: theme.colorSuccess }} /> 复制成功
</>
) : (
'复制'
)
}
>
<Button
icon={<CopyOutlined />}
className={styles.button}
onClick={() => {
copy(children);
setCopied();
}}
/>
</Tooltip>
</ConfigProvider>
)}

<SyntaxHighlighter language={language} type={type} syntaxThemes={syntaxThemes}>
<SyntaxHighlighter
language={language?.toLowerCase()}
type={type}
syntaxThemes={syntaxThemes}
>
{trim ? children.trim() : children}
</SyntaxHighlighter>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { default as DumiSiteProvider } from './components/DumiSiteProvider';
export { default as Features } from './components/Features';
export { default as Footer } from './components/Footer';
export { default as Hero } from './components/Hero';
export { Highlighter } from './components/Highlighter';
export { default as DumiSiteProvider } from './components/SiteProvider';
export { default as Toc } from './components/Toc';
2 changes: 1 addition & 1 deletion src/layouts/DocLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Helmet, useIntl, useLocation } from 'dumi';
import isEqual from 'fast-deep-equal';
import { memo, StrictMode, useEffect, type FC } from 'react';

import SiteProvider from '../../components/SiteProvider';
import SiteProvider from '../../components/DumiSiteProvider';
import { StoreUpdater } from '../../components/StoreUpdater';

import Docs from '../../pages/Docs';
Expand Down
12 changes: 10 additions & 2 deletions src/pages/Docs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Toc from 'dumi/theme/slots/Toc';

import { ApiHeader } from '../../components/ApiHeader';

import { isApiPageSel, siteTitleSel, useSiteStore } from '../../store';
import { apiHeaderSel, isApiPageSel, siteTitleSel, useSiteStore } from '../../store';
import { useStyles } from './styles';

const Docs: FC = memo(() => {
Expand All @@ -21,6 +21,7 @@ const Docs: FC = memo(() => {
const fm = useSiteStore((s) => s.routeMeta.frontmatter, isEqual);
const isApiPage = useSiteStore(isApiPageSel);
const siteTitle = useSiteStore(siteTitleSel);
const { pkg, docUrl, sourceUrl } = useSiteStore(apiHeaderSel);

const { styles, theme } = useStyles();

Expand All @@ -44,7 +45,14 @@ const Docs: FC = memo(() => {
<Center>
<Flexbox style={{ maxWidth: theme.contentMaxWidth, width: '100%' }}>
<Flexbox style={{ paddingBlock: 0, paddingInline: mobile ? 16 : 48 }}>
<ApiHeader title={fm.title} description={fm.description} />
<ApiHeader
title={fm.title}
description={fm.description}
pkg={pkg}
componentName={fm.atomId || fm.title}
sourceUrl={sourceUrl}
docsUrl={docUrl}
/>
</Flexbox>
</Flexbox>
</Center>
Expand Down
Loading

0 comments on commit 53d8aaf

Please sign in to comment.