From 724874b4ebacea1e55492393a30d0401be73033e Mon Sep 17 00:00:00 2001 From: ONLY-yours <1349021570@qq.com> Date: Wed, 1 Nov 2023 15:14:19 +0800 Subject: [PATCH 1/6] :sparkles: feat: new Components Snippet init --- src/Snippet/demos/index.tsx | 5 +++ src/Snippet/index.md | 14 +++++++++ src/Snippet/index.tsx | 61 +++++++++++++++++++++++++++++++++++ src/Snippet/style.ts | 63 +++++++++++++++++++++++++++++++++++++ src/index.ts | 1 + 5 files changed, 144 insertions(+) create mode 100644 src/Snippet/demos/index.tsx create mode 100644 src/Snippet/index.md create mode 100644 src/Snippet/index.tsx create mode 100644 src/Snippet/style.ts diff --git a/src/Snippet/demos/index.tsx b/src/Snippet/demos/index.tsx new file mode 100644 index 00000000..a5019aad --- /dev/null +++ b/src/Snippet/demos/index.tsx @@ -0,0 +1,5 @@ +import { Snippet } from '@ant-design/pro-editor'; + +export default () => { + return ; +}; diff --git a/src/Snippet/index.md b/src/Snippet/index.md new file mode 100644 index 00000000..ecd2f49a --- /dev/null +++ b/src/Snippet/index.md @@ -0,0 +1,14 @@ +--- +nav: 组件 +group: Content +title: Snippet +description: The Snippet component is used to display a code snippet with syntax highlighting. It can be customized with a symbol before the content and a language for syntax highlighting. The component is also copyable with a CopyButton included by default. +--- + +## Default + + + +## APIs + + diff --git a/src/Snippet/index.tsx b/src/Snippet/index.tsx new file mode 100644 index 00000000..c4045e0c --- /dev/null +++ b/src/Snippet/index.tsx @@ -0,0 +1,61 @@ +import { memo } from 'react'; + +import { Highlight } from '@ant-design/pro-editor'; + +import { DivProps } from 'react-layout-kit'; +import { useStyles } from './style'; + +export interface SnippetProps extends DivProps { + /** + * @description The content to be displayed inside the Snippet component + */ + children: string; + /** + * @description Whether the Snippet component is copyable or not + * @default true + */ + copyable?: boolean; + /** + * @description The language of the content inside the Snippet component + * @default 'tsx' + */ + language?: string; + /** + * @description Whether add spotlight background + * @default false + */ + spotlight?: boolean; + /** + * @description The symbol to be displayed before the content inside the Snippet component + */ + symbol?: string; + /** + * @description The type of the Snippet component + * @default 'ghost' + */ + type?: 'ghost' | 'block'; +} + +const Snippet = memo( + ({ + symbol, + language = 'tsx', + children, + // copyable = true, + type = 'ghost', + spotlight, + className, + ...props + }) => { + const { styles, cx } = useStyles(type); + return ( +
+ {/* {spotlight && } */} + {[symbol, children].filter(Boolean).join(' ')} + {/* {copyable && } */} +
+ ); + }, +); + +export { Snippet }; diff --git a/src/Snippet/style.ts b/src/Snippet/style.ts new file mode 100644 index 00000000..54e67c0e --- /dev/null +++ b/src/Snippet/style.ts @@ -0,0 +1,63 @@ +import { createStyles } from 'antd-style'; + +export const useStyles = createStyles(({ css, cx, token, prefixCls }, type: 'ghost' | 'block') => { + const typeStylish = css` + background-color: ${type === 'block' ? token.colorFillTertiary : 'transparent'}; + border: 1px solid ${type === 'block' ? 'transparent' : token.colorBorder}; + `; + + return { + container: cx( + typeStylish, + css` + position: relative; + + overflow: hidden; + display: flex; + gap: 8px; + align-items: center; + + max-width: 100%; + height: 38px; + padding: 0 8px 0 12px; + + border-radius: ${token.borderRadius}px; + + transition: background-color 100ms ${token.motionEaseOut}; + + &:hover { + background-color: ${token.colorFillTertiary}; + } + + .${prefixCls}-highlighter-shiki { + position: relative; + overflow: hidden; + flex: 1; + } + + .prism-code { + background: none !important; + } + + pre { + overflow-x: auto !important; + overflow-y: hidden !important; + display: flex; + align-items: center; + + width: 100%; + height: 36px !important; + margin: 0 !important; + + line-height: 1; + + background: none !important; + } + + code[class*='language-'] { + background: none !important; + } + `, + ), + }; +}); diff --git a/src/index.ts b/src/index.ts index bc81c741..517b94c1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,6 +27,7 @@ export type { CanvasInteractRule, InteractStatus, InteractStatusNode } from './I export { default as LevaPanel } from './LevaPanel'; export type { LevaPanelProps } from './LevaPanel'; export * from './ProBuilder'; +export * from './Snippet'; export * from './SortableList'; export * from './SortableTree'; export { default as TipGuide } from './TipGuide'; From fc0b503aefef310126c5e314e640db9af37e67b2 Mon Sep 17 00:00:00 2001 From: ONLY-yours <1349021570@qq.com> Date: Wed, 1 Nov 2023 16:55:36 +0800 Subject: [PATCH 2/6] :sparkles: feat: snippet almost done --- .../components/HighLighter/index.tsx | 3 +- src/Highlight/demos/config.js | 5 ++ src/Highlight/hooks/useHighlight.tsx | 13 +++-- src/Snippet/demos/index.tsx | 11 +++- src/Snippet/index.tsx | 48 ++++++++++------- src/Snippet/style.ts | 6 +-- src/components/CopyButton/index.tsx | 47 +++++++++++++++++ src/components/Spotlight/index.tsx | 51 +++++++++++++++++++ src/components/Spotlight/style.ts | 30 +++++++++++ src/hooks/useCopied.ts | 21 ++++++++ 10 files changed, 207 insertions(+), 28 deletions(-) create mode 100644 src/components/CopyButton/index.tsx create mode 100644 src/components/Spotlight/index.tsx create mode 100644 src/components/Spotlight/style.ts create mode 100644 src/hooks/useCopied.ts diff --git a/src/Highlight/components/HighLighter/index.tsx b/src/Highlight/components/HighLighter/index.tsx index afb75221..f2d51ec9 100644 --- a/src/Highlight/components/HighLighter/index.tsx +++ b/src/Highlight/components/HighLighter/index.tsx @@ -4,6 +4,7 @@ * 如果没有在 https://github.com/highlightjs/highlight.js/tree/master/src/languages 中查找是否支持,然后添加 * 优先支持主流语言,没有import在代码中使用的不会打包 */ +import { STUDIO_UI_PREFIX } from '@/theme'; import { Loading3QuartersOutlined as Loading } from '@ant-design/icons'; import classNames from 'classnames'; import { Center } from 'react-layout-kit'; @@ -18,7 +19,7 @@ export type ShikiProps = Pick< >; const HighLighter: React.FC = (props) => { - const { children, lineNumber = false, theme, language, prefixCls } = props; + const { children, lineNumber = false, theme, language, prefixCls = STUDIO_UI_PREFIX } = props; const { styles } = useStyles({ prefixCls, lineNumber, theme }); const { renderShiki, loading } = useShiki(language, theme); diff --git a/src/Highlight/demos/config.js b/src/Highlight/demos/config.js index b5406909..58e12d18 100644 --- a/src/Highlight/demos/config.js +++ b/src/Highlight/demos/config.js @@ -1,4 +1,9 @@ const configs = [ + { + language: 'bash', + text: 'Bash', + code: '#!/bin/bash\n\n###### CONFIG\nACCEPTED_HOSTS="/root/.hag_accepted.conf"\nBE_VERBOSE=false\n\nif [ "$UID" -ne 0 ]\nthen\n echo "Superuser rights required"\n exit 2\nfi\n\ngenApacheConf(){\n echo -e "# Host ${HOME_DIR}$1/$2 :"\n}\n\necho \'"quoted"\' | tr -d \\\\/" > text.txt\n\n', + }, { language: 'cpp', text: 'Cpp', diff --git a/src/Highlight/hooks/useHighlight.tsx b/src/Highlight/hooks/useHighlight.tsx index 970f51c9..55c7c0f9 100644 --- a/src/Highlight/hooks/useHighlight.tsx +++ b/src/Highlight/hooks/useHighlight.tsx @@ -1,6 +1,7 @@ import hljs from 'highlight.js/lib/core'; import { useEffect } from 'react'; +import { default as bash, default as sh } from 'highlight.js/lib/languages/bash'; import css from 'highlight.js/lib/languages/css'; import java from 'highlight.js/lib/languages/java'; import { default as javascript, default as jsx } from 'highlight.js/lib/languages/javascript'; @@ -26,6 +27,8 @@ export const languageMap = { java, python, sql, + bash, + sh, }; export const useHighlight = (language) => { @@ -41,10 +44,12 @@ export const useHighlight = (language) => { }, [language]); const renderHighlight = (content) => { - const result = ( - language ? hljs.highlight(language, content || '') : hljs.highlightAuto(content) - )?.value; - + let result = null; + if (language & languageMap[language]) { + result = hljs.highlight(language, content || '').value; + } else { + result = hljs.highlightAuto(content).value; + } return result; }; return { renderHighlight }; diff --git a/src/Snippet/demos/index.tsx b/src/Snippet/demos/index.tsx index a5019aad..efd3821c 100644 --- a/src/Snippet/demos/index.tsx +++ b/src/Snippet/demos/index.tsx @@ -1,5 +1,14 @@ import { Snippet } from '@ant-design/pro-editor'; export default () => { - return ; + return ( + + pnpm install @ant-design/pro-chat + + ); }; diff --git a/src/Snippet/index.tsx b/src/Snippet/index.tsx index c4045e0c..f1b0fd61 100644 --- a/src/Snippet/index.tsx +++ b/src/Snippet/index.tsx @@ -1,8 +1,9 @@ +import HighLighter from '@/Highlight/components/HighLighter'; +import CopyButton from '@/components/CopyButton'; +import Spotlight from '@/components/Spotlight'; import { memo } from 'react'; - -import { Highlight } from '@ant-design/pro-editor'; - import { DivProps } from 'react-layout-kit'; +import { getPrefixCls } from '..'; import { useStyles } from './style'; export interface SnippetProps extends DivProps { @@ -34,28 +35,37 @@ export interface SnippetProps extends DivProps { * @default 'ghost' */ type?: 'ghost' | 'block'; + + prefixCls?: string; } -const Snippet = memo( - ({ - symbol, +const Snippet = memo((props) => { + const { + symbol = '$', language = 'tsx', children, - // copyable = true, + copyable = true, + prefixCls: customPrefixCls, type = 'ghost', spotlight, className, - ...props - }) => { - const { styles, cx } = useStyles(type); - return ( -
- {/* {spotlight && } */} - {[symbol, children].filter(Boolean).join(' ')} - {/* {copyable && } */} -
- ); - }, -); + ...rest + } = props; + const prefixCls = getPrefixCls('snippet', customPrefixCls); + + const { styles, cx } = useStyles({ + type, + prefixCls, + }); + return ( +
+ {spotlight && } + + {[symbol, children].filter(Boolean).join(' ')} + + {copyable && } +
+ ); +}); export { Snippet }; diff --git a/src/Snippet/style.ts b/src/Snippet/style.ts index 54e67c0e..74dd6430 100644 --- a/src/Snippet/style.ts +++ b/src/Snippet/style.ts @@ -1,6 +1,6 @@ import { createStyles } from 'antd-style'; -export const useStyles = createStyles(({ css, cx, token, prefixCls }, type: 'ghost' | 'block') => { +export const useStyles = createStyles(({ css, cx, token }, { type, prefixCls }) => { const typeStylish = css` background-color: ${type === 'block' ? token.colorFillTertiary : 'transparent'}; border: 1px solid ${type === 'block' ? 'transparent' : token.colorBorder}; @@ -8,6 +8,7 @@ export const useStyles = createStyles(({ css, cx, token, prefixCls }, type: 'gho return { container: cx( + `${prefixCls}-container`, typeStylish, css` position: relative; @@ -16,7 +17,6 @@ export const useStyles = createStyles(({ css, cx, token, prefixCls }, type: 'gho display: flex; gap: 8px; align-items: center; - max-width: 100%; height: 38px; padding: 0 8px 0 12px; @@ -29,7 +29,7 @@ export const useStyles = createStyles(({ css, cx, token, prefixCls }, type: 'gho background-color: ${token.colorFillTertiary}; } - .${prefixCls}-highlighter-shiki { + .${prefixCls}-shiki { position: relative; overflow: hidden; flex: 1; diff --git a/src/components/CopyButton/index.tsx b/src/components/CopyButton/index.tsx new file mode 100644 index 00000000..14a0e257 --- /dev/null +++ b/src/components/CopyButton/index.tsx @@ -0,0 +1,47 @@ +import copy from 'copy-to-clipboard'; +import { Copy } from 'lucide-react'; +import { memo } from 'react'; + +import ActionIcon from '@/ActionIcon'; +import { useCopied } from '@/hooks/useCopied'; +import { type TooltipProps } from 'antd'; +import { DivProps } from 'react-layout-kit'; + +export interface CopyButtonProps extends DivProps { + /** + * @description Additional class name + */ + className?: string; + /** + * @description The text content to be copied + */ + content: string; + /** + * @description The placement of the tooltip + * @enum ['top', 'left', 'right', 'bottom', 'topLeft', 'topRight', 'bottomLeft', 'bottomRight', 'leftTop', 'leftBottom', 'rightTop', 'rightBottom'] + * @default 'right' + */ + placement?: TooltipProps['placement']; +} + +const CopyButton = memo( + ({ content, className, placement = 'right', ...props }) => { + const { copied, setCopied } = useCopied(); + + return ( + } + onClick={() => { + copy(content); + setCopied(); + }} + placement={placement} + title={copied ? '✅ Success' : 'Copy'} + /> + ); + }, +); + +export default CopyButton; diff --git a/src/components/Spotlight/index.tsx b/src/components/Spotlight/index.tsx new file mode 100644 index 00000000..a79ecdac --- /dev/null +++ b/src/components/Spotlight/index.tsx @@ -0,0 +1,51 @@ +import { memo, useEffect, useRef, useState } from 'react'; +import { DivProps } from 'react-layout-kit'; +import { useStyles } from './style'; + +const useMouseOffset = (): any => { + const [offset, setOffset] = useState<{ x: number; y: number }>(); + const [outside, setOutside] = useState(true); + const reference = useRef(); + + useEffect(() => { + if (reference.current && reference.current.parentElement) { + const element = reference.current.parentElement; + + // debounce? + const onMouseMove = (e: MouseEvent) => { + const bound = element.getBoundingClientRect(); + setOffset({ x: e.clientX - bound.x, y: e.clientY - bound.y }); + setOutside(false); + }; + + const onMouseLeave = () => { + setOutside(true); + }; + element.addEventListener('mousemove', onMouseMove); + element.addEventListener('mouseleave', onMouseLeave); + return () => { + element.removeEventListener('mousemove', onMouseMove); + element.removeEventListener('mouseleave', onMouseLeave); + }; + } + }, []); + + return [offset, outside, reference] as const; +}; + +export interface SpotlightProps extends DivProps { + /** + * @description The size of the spotlight circle + * @default 64 + */ + size?: number; +} + +const Spotlight = memo(({ className, size = 64, ...properties }) => { + const [offset, outside, reference] = useMouseOffset(); + const { styles, cx } = useStyles({ offset, outside, size }); + + return
; +}); + +export default Spotlight; diff --git a/src/components/Spotlight/style.ts b/src/components/Spotlight/style.ts new file mode 100644 index 00000000..279b5f7a --- /dev/null +++ b/src/components/Spotlight/style.ts @@ -0,0 +1,30 @@ +import { createStyles } from 'antd-style'; + +export const useStyles = createStyles( + ( + { css, token, isDarkMode }, + { offset, outside, size }: { offset: { x: number; y: number }; outside: boolean; size: number }, + ) => { + const spotlightX = (offset?.x ?? 0) + 'px'; + const spotlightY = (offset?.y ?? 0) + 'px'; + const spotlightOpacity = outside ? '0' : '.1'; + const spotlightSize = size + 'px'; + return css` + pointer-events: none; + + position: absolute; + z-index: 1; + inset: 0; + + opacity: ${spotlightOpacity}; + background: radial-gradient( + ${spotlightSize} circle at ${spotlightX} ${spotlightY}, + ${isDarkMode ? token.colorText : '#fff'}, + ${isDarkMode ? 'transparent' : token.colorTextQuaternary} + ); + border-radius: inherit; + + transition: all 0.2s; + `; + }, +); diff --git a/src/hooks/useCopied.ts b/src/hooks/useCopied.ts new file mode 100644 index 00000000..360e45f4 --- /dev/null +++ b/src/hooks/useCopied.ts @@ -0,0 +1,21 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; + +export const useCopied = () => { + const [copied, setCopy] = useState(false); + + useEffect(() => { + if (!copied) return; + + const timer = setTimeout(() => { + setCopy(false); + }, 2000); + + return () => { + clearTimeout(timer); + }; + }, [copied]); + + const setCopied = useCallback(() => setCopy(true), []); + + return useMemo(() => ({ copied, setCopied }), [copied]); +}; From 9621cc263791d1857c792696ef0bebdc06f92001 Mon Sep 17 00:00:00 2001 From: rdmclin2 Date: Mon, 6 Nov 2023 11:54:18 +0800 Subject: [PATCH 3/6] :sparkles: feat: use shikiji to replace shikiji-es feat: use shikiji to replace shikiji-es --- package.json | 2 +- .../components/HighLighter/index.tsx | 9 +- src/Highlight/hooks/useShiki.tsx | 8 +- tests/__snapshots__/demo.test.tsx.snap | 384 ++++++++++++++++-- 4 files changed, 353 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index 08f50a82..bffd27d5 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "react-rnd": "^10.4.1", "reactflow": "^11.8.3", "rxjs": "^7.8.1", - "shiki-es": "~0.2.0", + "shikiji": "^0.6.12", "type-fest": "^3.13.1", "umi-request": "^1.4.0", "use-merge-value": "^1.2.0", diff --git a/src/Highlight/components/HighLighter/index.tsx b/src/Highlight/components/HighLighter/index.tsx index f2d51ec9..72e6d1bf 100644 --- a/src/Highlight/components/HighLighter/index.tsx +++ b/src/Highlight/components/HighLighter/index.tsx @@ -4,6 +4,7 @@ * 如果没有在 https://github.com/highlightjs/highlight.js/tree/master/src/languages 中查找是否支持,然后添加 * 优先支持主流语言,没有import在代码中使用的不会打包 */ +import { THEME_LIGHT } from '@/Highlight/theme'; import { STUDIO_UI_PREFIX } from '@/theme'; import { Loading3QuartersOutlined as Loading } from '@ant-design/icons'; import classNames from 'classnames'; @@ -19,7 +20,13 @@ export type ShikiProps = Pick< >; const HighLighter: React.FC = (props) => { - const { children, lineNumber = false, theme, language, prefixCls = STUDIO_UI_PREFIX } = props; + const { + children, + lineNumber = false, + theme = THEME_LIGHT, + language, + prefixCls = STUDIO_UI_PREFIX, + } = props; const { styles } = useStyles({ prefixCls, lineNumber, theme }); const { renderShiki, loading } = useShiki(language, theme); diff --git a/src/Highlight/hooks/useShiki.tsx b/src/Highlight/hooks/useShiki.tsx index 72b38f38..70d63194 100644 --- a/src/Highlight/hooks/useShiki.tsx +++ b/src/Highlight/hooks/useShiki.tsx @@ -1,12 +1,7 @@ import { useEffect, useState } from 'react'; -import { getHighlighter, setCDN, type Highlighter } from 'shiki-es'; +import { getHighlighter, type Highlighter } from 'shikiji'; import { themeConfig } from '../theme'; -// 国内使用 CDN 加速, 测试环境为 node,会加载失败 -if (process.env.NODE_ENV !== 'test') { - setCDN('https://npm.elemecdn.com/shiki-es/dist/assets'); -} - // 目前支持的语言列表 export const languageMap = [ 'javascript', @@ -21,6 +16,7 @@ export const languageMap = [ 'java', 'python', 'sql', + 'sh', ]; export const useShiki = (language, theme) => { diff --git a/tests/__snapshots__/demo.test.tsx.snap b/tests/__snapshots__/demo.test.tsx.snap index f176b290..5719593e 100644 --- a/tests/__snapshots__/demo.test.tsx.snap +++ b/tests/__snapshots__/demo.test.tsx.snap @@ -16896,40 +16896,46 @@ exports[` > renders basic.tsx correctly 1`] = ` class="undefined-content emotion-5" > + + public + + + + static + + + + void + + - - public - - - - static - - - - void - - main + ( - (String[] args) + + String + + [] args - + ) - { + { @@ -17279,40 +17285,46 @@ exports[` > renders lineNumber.tsx correctly 1`] = ` class="undefined-content emotion-6" > + + public + + + + static + + + + void + + - - public - - - - static - - - - void - - main + ( - (String[] args) + + String + + [] args - + ) - { + { @@ -20423,6 +20435,294 @@ exports[` > renders button.tsx correctly 1`] = `
`; +exports[` > renders index.tsx correctly 1`] = ` +.emotion-0 { + background-color: transparent; + border: 1px solid #d9d9d9; + position: relative; + overflow: hidden; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + gap: 8px; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + max-width: 100%; + height: 38px; + padding: 0 8px 0 12px; + border-radius: 6px; + -webkit-transition: background-color 100ms cubic-bezier(0.215, 0.61, 0.355, 1); + transition: background-color 100ms cubic-bezier(0.215, 0.61, 0.355, 1); +} + +.emotion-0:hover { + background-color: rgba(0, 0, 0, 0.04); +} + +.emotion-0 .studio-snippet-shiki { + position: relative; + overflow: hidden; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; +} + +.emotion-0 .prism-code { + background: none!important; +} + +.emotion-0 pre { + overflow-x: auto!important; + overflow-y: hidden!important; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + height: 36px!important; + margin: 0!important; + line-height: 1; + background: none!important; +} + +.emotion-0 code[class*='language-'] { + background: none!important; +} + +.emotion-1 { + display: block; + overflow-x: auto; + color: #333333; + background-color: #666666; +} + +.emotion-1 .hljs-comment, +.emotion-1 .hljs-quote { + color: #aaaaaa; +} + +.emotion-1 .hljs-variable, +.emotion-1 .hljs-attribute, +.emotion-1 .hljs-template-variable, +.emotion-1 .hljs-tag, +.emotion-1 .hljs-name, +.emotion-1 .hljs-selector-id, +.emotion-1 .hljs-selector-class, +.emotion-1 .hljs-regexp, +.emotion-1 .hljs-title, +.emotion-1 .hljs-deletion { + color: #ec5e41; +} + +.emotion-1 .hljs-builtin-name, +.emotion-1 .hljs-literal, +.emotion-1 .hljs-type, +.emotion-1 .hljs-params, +.emotion-1 .hljs-meta, +.emotion-1 .hljs-link { + color: #ff802b; +} + +.emotion-1 .hljs-string, +.emotion-1 .hljs-number, +.emotion-1 .hljs-symbol, +.emotion-1 .hljs-bullet, +.emotion-1 .hljs-addition { + color: #55b467; +} + +.emotion-1 .hljs-keyword, +.emotion-1 .hljs-doctag, +.emotion-1 .hljs-built_in, +.emotion-1 .hljs-selector-tag, +.emotion-1 .hljs-section { + color: #369eff; +} + +.emotion-1 .hljs-emphasis { + font-style: italic; +} + +.emotion-1 .hljs-strong { + font-weight: bold; +} + +.emotion-2 { + width: 100%; +} + +.emotion-3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 8px; +} + +.emotion-4 { + -webkit-backdrop-filter: saturate(180%) blur(10px); + backdrop-filter: saturate(180%) blur(10px); + position: absolute; + top: 0; + right: 0; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + height: 36px; + padding: 0 8px; + font-family: 'SFMono-Regular',Consolas,'Liberation Mono',Menlo,Courier,monospace; + color: #aaaaaa; + border-radius: 6; +} + +.emotion-5 { + color: #aaaaaa; +} + +.emotion-6 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-transition: color 600ms cubic-bezier(0.215, 0.61, 0.355, 1),scale 400ms cubic-bezier(0.215, 0.61, 0.355, 1),background-color 100ms cubic-bezier(0.215, 0.61, 0.355, 1); + transition: color 600ms cubic-bezier(0.215, 0.61, 0.355, 1),scale 400ms cubic-bezier(0.215, 0.61, 0.355, 1),background-color 100ms cubic-bezier(0.215, 0.61, 0.355, 1); +} + +.emotion-6:hover { + color: rgba(0, 0, 0, 0.88)!important; +} + +.emotion-6:active { + scale: 0.8; + color: rgba(0, 0, 0, 0.88); +} + +
+
+
+      
+        
+          
+            
+          
+        
+      
+ $ pnpm install + + @ant + + -design/pro-chat +
+
+
+ + + + Highlighting... +
+ +
+
+`; + exports[` > renders Basic.tsx correctly 1`] = ` .emotion-0 { display: -webkit-box; From 181c49484d4de954d08cc41ef41a1cc659be3dc4 Mon Sep 17 00:00:00 2001 From: rdmclin2 Date: Mon, 6 Nov 2023 12:31:20 +0800 Subject: [PATCH 4/6] :sparkles: feat: snippet auto theme" auto theme --- src/Snippet/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Snippet/index.tsx b/src/Snippet/index.tsx index f1b0fd61..e7d4dd0b 100644 --- a/src/Snippet/index.tsx +++ b/src/Snippet/index.tsx @@ -1,6 +1,7 @@ import HighLighter from '@/Highlight/components/HighLighter'; import CopyButton from '@/components/CopyButton'; import Spotlight from '@/components/Spotlight'; +import { useThemeMode } from 'antd-style'; import { memo } from 'react'; import { DivProps } from 'react-layout-kit'; import { getPrefixCls } from '..'; @@ -52,6 +53,7 @@ const Snippet = memo((props) => { ...rest } = props; const prefixCls = getPrefixCls('snippet', customPrefixCls); + const { isDarkMode } = useThemeMode(); const { styles, cx } = useStyles({ type, @@ -60,7 +62,7 @@ const Snippet = memo((props) => { return (
{spotlight && } - + {[symbol, children].filter(Boolean).join(' ')} {copyable && } From 5305a67a6d4304996717617430a464ee5c03b050 Mon Sep 17 00:00:00 2001 From: rdmclin2 Date: Mon, 6 Nov 2023 12:52:27 +0800 Subject: [PATCH 5/6] :recycle: refactor: remove lucide --- package.json | 1 - src/ContextMenu/demos/index.tsx | 5 ++--- src/Highlight/wrapper.tsx | 4 ++-- src/Snippet/demos/index.tsx | 11 +---------- src/Snippet/style.ts | 7 +------ src/components/CopyButton/index.tsx | 4 ++-- 6 files changed, 8 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index bffd27d5..9d860668 100644 --- a/package.json +++ b/package.json @@ -141,7 +141,6 @@ "husky": "^8.0.3", "jsdom": "^22.1.0", "lint-staged": "^13.3.0", - "lucide-react": "latest", "prettier-plugin-organize-imports": "^3.2.3", "prettier-plugin-packagejson": "^2.4.5", "react": "^18.2.0", diff --git a/src/ContextMenu/demos/index.tsx b/src/ContextMenu/demos/index.tsx index e34c1657..a14a9015 100644 --- a/src/ContextMenu/demos/index.tsx +++ b/src/ContextMenu/demos/index.tsx @@ -1,6 +1,5 @@ -import { CopyOutlined, ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons'; +import { CopyOutlined, ExpandOutlined, ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons'; import { ContextMenu } from '@ant-design/pro-editor'; -import { BoxSelectIcon } from 'lucide-react'; export default () => { return ( @@ -17,7 +16,7 @@ export default () => { { key: 'selectAll', label: '选择全部', - icon: , + icon: , shortcut: ['meta', 'A'], }, { label: '放大', key: 'zoomIn', icon: }, diff --git a/src/Highlight/wrapper.tsx b/src/Highlight/wrapper.tsx index 753510e3..a96ecc4d 100644 --- a/src/Highlight/wrapper.tsx +++ b/src/Highlight/wrapper.tsx @@ -1,6 +1,6 @@ +import { DownOutlined, RightOutlined } from '@ant-design/icons'; 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 '..'; @@ -49,7 +49,7 @@ export const FullFeatureWrapper = memo : } + icon={expand ? : } onClick={() => setExpand(!expand)} size={24} /> diff --git a/src/Snippet/demos/index.tsx b/src/Snippet/demos/index.tsx index efd3821c..d10600dd 100644 --- a/src/Snippet/demos/index.tsx +++ b/src/Snippet/demos/index.tsx @@ -1,14 +1,5 @@ import { Snippet } from '@ant-design/pro-editor'; export default () => { - return ( - - pnpm install @ant-design/pro-chat - - ); + return pnpm install @ant-design/pro-chat; }; diff --git a/src/Snippet/style.ts b/src/Snippet/style.ts index 74dd6430..24447590 100644 --- a/src/Snippet/style.ts +++ b/src/Snippet/style.ts @@ -12,9 +12,8 @@ export const useStyles = createStyles(({ css, cx, token }, { type, prefixCls }) typeStylish, css` position: relative; - overflow: hidden; - display: flex; + display: inline-flex; gap: 8px; align-items: center; max-width: 100%; @@ -35,10 +34,6 @@ export const useStyles = createStyles(({ css, cx, token }, { type, prefixCls }) flex: 1; } - .prism-code { - background: none !important; - } - pre { overflow-x: auto !important; overflow-y: hidden !important; diff --git a/src/components/CopyButton/index.tsx b/src/components/CopyButton/index.tsx index 14a0e257..67c92baf 100644 --- a/src/components/CopyButton/index.tsx +++ b/src/components/CopyButton/index.tsx @@ -1,5 +1,5 @@ +import { CopyOutlined } from '@ant-design/icons'; import copy from 'copy-to-clipboard'; -import { Copy } from 'lucide-react'; import { memo } from 'react'; import ActionIcon from '@/ActionIcon'; @@ -32,7 +32,7 @@ const CopyButton = memo( } + icon={} onClick={() => { copy(content); setCopied(); From efa1bb14e4dd4fb6bcaafc7eb96bc731bc3d0b53 Mon Sep 17 00:00:00 2001 From: rdmclin2 Date: Mon, 6 Nov 2023 12:56:33 +0800 Subject: [PATCH 6/6] :camera_flash: build: update snapshot" --- tests/__snapshots__/demo.test.tsx.snap | 123 ++++++++++++------------- 1 file changed, 61 insertions(+), 62 deletions(-) diff --git a/tests/__snapshots__/demo.test.tsx.snap b/tests/__snapshots__/demo.test.tsx.snap index 5719593e..799ca3de 100644 --- a/tests/__snapshots__/demo.test.tsx.snap +++ b/tests/__snapshots__/demo.test.tsx.snap @@ -18805,22 +18805,26 @@ exports[` > renders wrapper.tsx correctly 1`] = ` - - - + +
> renders wrapper.tsx correctly 1`] = ` - - - + +
> renders index.tsx correctly 1`] = ` border: 1px solid #d9d9d9; position: relative; overflow: hidden; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; gap: 8px; -webkit-align-items: center; -webkit-box-align: center; @@ -20470,10 +20478,6 @@ exports[` > renders index.tsx correctly 1`] = ` flex: 1; } -.emotion-0 .prism-code { - background: none!important; -} - .emotion-0 pre { overflow-x: auto!important; overflow-y: hidden!important; @@ -20635,7 +20639,6 @@ exports[` > renders index.tsx correctly 1`] = `
 > renders index.tsx correctly 1`] = `
       
-        
-          
-          
-        
+          
+