From f7b6ece5bb905b503f816fe0fcad1e63f7423912 Mon Sep 17 00:00:00 2001 From: ONLY-yours <1349021570@qq.com> Date: Mon, 30 Oct 2023 19:57:42 +0800 Subject: [PATCH 1/5] :sparkles: feat: highlight add pro wrapper mode --- src/Highlight/components/CopyButton/index.tsx | 11 +- .../components/HighLightJS/index.tsx | 2 +- .../components/HighLighter/index.tsx | 2 +- src/Highlight/defalut.tsx | 112 +++++++++++++++++ src/Highlight/demos/wrapper.tsx | 39 ++++++ src/Highlight/index.md | 6 + src/Highlight/index.tsx | 118 ++---------------- src/Highlight/style.ts | 62 ++++++++- src/Highlight/wrapper.tsx | 94 ++++++++++++++ 9 files changed, 331 insertions(+), 115 deletions(-) create mode 100644 src/Highlight/defalut.tsx create mode 100644 src/Highlight/demos/wrapper.tsx create mode 100644 src/Highlight/wrapper.tsx diff --git a/src/Highlight/components/CopyButton/index.tsx b/src/Highlight/components/CopyButton/index.tsx index d45ec09b..b7f3acb2 100644 --- a/src/Highlight/components/CopyButton/index.tsx +++ b/src/Highlight/components/CopyButton/index.tsx @@ -10,18 +10,19 @@ interface CopyButtonProps { /** * @title 复制按钮点击后回调 */ - onCopy: (content: any) => void; + onCopy?: (content: any) => void; /** * @title 主题 * @description 主题颜色, dark 黑色主题,light 白色主题 * @default "light" */ - theme: ThemeType; - prefixCls: string; + theme?: ThemeType; + prefixCls?: string; + style?: React.CSSProperties; } const CopyButton: React.FC = (props) => { - const { content, onCopy, theme, prefixCls } = props; + const { content, onCopy, theme = 'light', prefixCls, style } = props; const [copyId, setCopyId] = useState(); const { styles } = useStyles({ prefixCls, theme }); @@ -44,7 +45,7 @@ const CopyButton: React.FC = (props) => { if (onCopy) onCopy(content); }} > - diff --git a/src/Highlight/components/HighLightJS/index.tsx b/src/Highlight/components/HighLightJS/index.tsx index 69ef015a..1cf44b05 100644 --- a/src/Highlight/components/HighLightJS/index.tsx +++ b/src/Highlight/components/HighLightJS/index.tsx @@ -6,8 +6,8 @@ */ import classNames from 'classnames'; import { useEffect, useState } from 'react'; +import { HighlightProps } from '../../defalut'; import { useHighlight } from '../../hooks/useHighlight'; -import { HighlightProps } from '../../index'; import { THEME_LIGHT } from '../../theme'; import HighlightCell from '../HighlightCell'; import { useStyles } from './style'; diff --git a/src/Highlight/components/HighLighter/index.tsx b/src/Highlight/components/HighLighter/index.tsx index 3d335fb3..afb75221 100644 --- a/src/Highlight/components/HighLighter/index.tsx +++ b/src/Highlight/components/HighLighter/index.tsx @@ -7,8 +7,8 @@ import { Loading3QuartersOutlined as Loading } from '@ant-design/icons'; import classNames from 'classnames'; import { Center } from 'react-layout-kit'; +import { HighlightProps } from '../../defalut'; import { useShiki } from '../../hooks/useShiki'; -import { HighlightProps } from '../../index'; import HighLightJS from '../HighLightJS'; import { useStyles } from './style'; diff --git a/src/Highlight/defalut.tsx b/src/Highlight/defalut.tsx new file mode 100644 index 00000000..12cde406 --- /dev/null +++ b/src/Highlight/defalut.tsx @@ -0,0 +1,112 @@ +import classNames from 'classnames'; +import { createRef } from 'react'; +import { getPrefixCls } from '../theme'; +import CopyButton from './components/CopyButton'; +import HighLighter from './components/HighLighter'; +import { useKeyDownCopyEvent } from './hooks/useKeyDownCopyEvent'; +import { useStyles } from './style'; +import { THEME_LIGHT, ThemeType } from './theme'; + +export interface HighlightProps { + /** + * @description 样式 + * @ignore + */ + style?: React.CSSProperties; + /** + * @description className 类名 + * @ignore + */ + className?: string; + /** + * @description 类名前缀 + * @ignore + */ + prefixCls?: string; + /** + * @title 指定语言 + * @description 指定语言 + * @renderType select + * @default "typescript" + */ + language: string; + /** + * @title 主题 + * @description 主题颜色, dark 黑色主题,light 白色主题 + * @default "light" + */ + theme?: ThemeType; + /** + * @title 高亮内容 + * @description 高亮内容 + */ + children?: any; + /** + * @title 是否使用要使用行号 + * @description 是否需要展示代码块左侧的行号 + * @default false + */ + lineNumber?: boolean; + /** + * @title 是否展示复制按钮 + * @description 是否需要展示复制按钮 + * @default true + */ + copyable?: boolean; + /** + * @title 复制按钮点击后回调 + */ + onCopy?: (children: any) => void; + /** + * 高亮类型 + */ + type?: 'pure' | 'block'; + /** + * 是否需要默认外层 wrapper + */ + containerWrapper?: boolean; +} + +const HighlightBase: React.FC = (props) => { + const { + children, + style, + className, + lineNumber = false, + copyable = true, + theme = THEME_LIGHT, + language, + prefixCls: customPrefixCls, + type = 'block', + onCopy, + } = props; + const prefixCls = getPrefixCls('highlight', customPrefixCls); + const { styles } = useStyles({ prefixCls, theme, type }); + const codeRef = createRef(); + useKeyDownCopyEvent(codeRef, onCopy); + + return ( + <> +
+ {copyable && ( + + )} + + {children} + +
+ + ); +}; + +export { HighlightBase }; diff --git a/src/Highlight/demos/wrapper.tsx b/src/Highlight/demos/wrapper.tsx new file mode 100644 index 00000000..2d164273 --- /dev/null +++ b/src/Highlight/demos/wrapper.tsx @@ -0,0 +1,39 @@ +/** + * title: wrapper used + */ + +import { Highlight } from '@ant-design/pro-editor'; +import { Space } from 'antd'; + +export default () => ( + + { + console.log('复制代码', children); + }} + > + {`public class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello World!"); + } + }`} + + { + console.log('复制代码', children); + }} + > + {`public class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello World!"); + } + }`} + + +); diff --git a/src/Highlight/index.md b/src/Highlight/index.md index 142eab1f..0c32720d 100644 --- a/src/Highlight/index.md +++ b/src/Highlight/index.md @@ -30,6 +30,12 @@ group: 基础组件 +### 外层默认容器包裹 + +你可以通过 `containerWrapper` 来默认渲染一个外层的容器,改容器提供一些基本能力:展开关闭、语言切换 + + + ## API 参数 ### Highlight diff --git a/src/Highlight/index.tsx b/src/Highlight/index.tsx index d922b8c7..1514d7c5 100644 --- a/src/Highlight/index.tsx +++ b/src/Highlight/index.tsx @@ -1,109 +1,15 @@ -import classNames from 'classnames'; -import { createRef } from 'react'; -import { getPrefixCls } from '../theme'; -import CopyButton from './components/CopyButton'; -import HighLighter from './components/HighLighter'; -import { useKeyDownCopyEvent } from './hooks/useKeyDownCopyEvent'; -import { useStyles } from './style'; -import { THEME_LIGHT, ThemeType } from './theme'; - -export interface HighlightProps { - /** - * @description 样式 - * @ignore - */ - style?: React.CSSProperties; - /** - * @description className 类名 - * @ignore - */ - className?: string; - /** - * @description 类名前缀 - * @ignore - */ - prefixCls?: string; - /** - * @title 指定语言 - * @description 指定语言 - * @renderType select - * @default "typescript" - */ - language: string; - /** - * @title 主题 - * @description 主题颜色, dark 黑色主题,light 白色主题 - * @default "light" - */ - theme?: ThemeType; - /** - * @title 高亮内容 - * @description 高亮内容 - */ - children?: any; - /** - * @title 是否使用要使用行号 - * @description 是否需要展示代码块左侧的行号 - * @default false - */ - lineNumber?: boolean; - /** - * @title 是否展示复制按钮 - * @description 是否需要展示复制按钮 - * @default true - */ - copyable?: boolean; - /** - * @title 复制按钮点击后回调 - */ - onCopy?: (children: any) => void; - /** - * 高亮类型 - */ - type?: 'pure' | 'block'; -} - -const Highlight: React.FC = (props) => { - const { - children, - style, - className, - lineNumber = false, - copyable = true, - theme = THEME_LIGHT, - language, - prefixCls: customPrefixCls, - type = 'block', - onCopy, - } = props; - - const prefixCls = getPrefixCls('highlight', customPrefixCls); - const { styles } = useStyles({ prefixCls, theme, type }); - const codeRef = createRef(); - useKeyDownCopyEvent(codeRef, onCopy); - - return ( - <> -
- {copyable && ( - - )} - - {children} - -
- - ); +import { HighlightBase, HighlightProps } from './defalut'; +import FullFeatureWrapper from './wrapper'; + +const Highlight = ( + props: HighlightProps & { + containerWrapper: boolean; + }, +) => { + if (props?.containerWrapper) { + return ; + } + return ; }; export { Highlight }; diff --git a/src/Highlight/style.ts b/src/Highlight/style.ts index f01f03dd..4f3d9f61 100644 --- a/src/Highlight/style.ts +++ b/src/Highlight/style.ts @@ -1,4 +1,5 @@ -import { createStyles } from '../theme'; +import Color from 'color'; +import { STUDIO_UI_PREFIX, createStyles } from '../theme'; import { getThemeColor } from './theme/colors'; interface IHighlightStyleProps { @@ -10,14 +11,41 @@ interface IHighlightStyleProps { export const useStyles = createStyles( ({ css, cx, token }, { prefixCls, theme, type }: IHighlightStyleProps) => { const prefix = `${prefixCls}`; - const { colorFillTertiary } = getThemeColor(theme === 'dark'); + const { colorFillTertiary, colorText, colorTextSecondary } = getThemeColor(theme === 'dark'); const typeStylish = css` background-color: ${type === 'block' ? colorFillTertiary : 'transparent'}; border: 1px solid ${type === 'block' ? colorFillTertiary : 'transparent'}; `; + const lighterTypeStylish = css` + background-color: ${type === 'block' + ? Color(colorFillTertiary).alpha(0.9).hsl().string() + : 'transparent'}; + `; + return { + wrapper: cx( + `${prefix}-wrapper`, + lighterTypeStylish, + css` + border-radius: ${token.borderRadius}px; + .${prefix}-copy { + background-color: transparent; + position: inherit; + width: 30px; + padding-left: 6px; + } + `, + ), + header: cx( + `${prefix}-header`, + css` + padding: 4px 8px; + background: rgba(0, 0, 0, 0.02); + width: auto !important; // override self width + `, + ), container: cx( `${prefix}-container`, typeStylish, @@ -39,6 +67,36 @@ export const useStyles = createStyles( } `, ), + trigger: css` + min-width: 100px; + display: flex; + justify-content: center; + `, + expandIcon: css` + color: ${colorText}; + &:hover { + .${STUDIO_UI_PREFIX}-btn-icon { + color: ${colorText} !important; + } + } + `, + select: css` + min-width: 100px; + .${STUDIO_UI_PREFIX}-btn { + color: ${colorText}; + &:hover { + color: ${colorTextSecondary} !important; + } + } + .${STUDIO_UI_PREFIX}-select-selector { + padding-inline-end: 4px !important; + } + .${STUDIO_UI_PREFIX}-select-selection-overflow-item-suffix { + .${STUDIO_UI_PREFIX}-select-selection-search { + display: none; + } + } + `, }; }, ); diff --git a/src/Highlight/wrapper.tsx b/src/Highlight/wrapper.tsx new file mode 100644 index 00000000..0a69be90 --- /dev/null +++ b/src/Highlight/wrapper.tsx @@ -0,0 +1,94 @@ +import { ActionIcon, Button, Select, type SelectProps } from '@ant-design/pro-editor'; +import classNames from 'classnames'; +import { ChevronDown, ChevronRight } from 'lucide-react'; +import { memo, useState } from 'react'; +import { DivProps, Flexbox } from 'react-layout-kit'; +import { getPrefixCls } from '..'; +import CopyButton from './components/CopyButton'; +import { HighlightBase, HighlightProps } from './defalut'; +import { languageMap } from './hooks/useHighlight'; +import { useStyles } from './style'; +import { THEME_LIGHT } from './theme'; + +export interface HighlighterWrapperProps extends DivProps { + /** + * @description The code content to be highlighted + */ + children?: any; + /** + * @description The language of the code content + */ + language: string; +} + +const options: SelectProps['options'] = []; + +Object.entries(languageMap).forEach(([key, value]) => { + console.log(key, value); + options.push({ + label: key, + value: key.toLowerCase(), + }); +}); + +export const FullFeatureWrapper = memo((props) => { + const { + children, + language = 'markdown', + className, + style, + prefixCls: customPrefixCls, + theme = THEME_LIGHT, + type = 'block', + } = props || {}; + const prefixCls = getPrefixCls('highlight', customPrefixCls); + const [expand, setExpand] = useState(true); + const [lang, setLang] = useState(language); + const { styles } = useStyles({ + prefixCls, + theme, + type, + }); + + return ( +
+ + : } + onClick={() => setExpand(!expand)} + size={24} + /> + + +
+ + + +