mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-06 05:09:09 +08:00
refactor(CodeEditor): improve code editor props (#9653)
* refactor(CodeEditor): improve props for clarity * refactor: update CodeEditor usage * refactor: change unwrapped to wrapped * fix: CodeViewer unwrap * refactor: simplify code viewer border radius, add comments
This commit is contained in:
parent
4f620aed8d
commit
d4e024f42d
@ -145,9 +145,10 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
|||||||
language="html"
|
language="html"
|
||||||
editable={true}
|
editable={true}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
style={{ height: '100%' }}
|
height="100%"
|
||||||
expanded
|
expanded={false}
|
||||||
unwrapped={false}
|
wrapped
|
||||||
|
style={{ minHeight: 0 }}
|
||||||
options={{
|
options={{
|
||||||
stream: true, // FIXME: 避免多余空行
|
stream: true, // FIXME: 避免多余空行
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
@ -388,12 +389,8 @@ const CodeSection = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: grid;
|
||||||
.monaco-editor,
|
grid-template-rows: 1fr auto;
|
||||||
.cm-editor,
|
|
||||||
.cm-scroller {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const PreviewSection = styled.div`
|
const PreviewSection = styled.div`
|
||||||
|
|||||||
@ -100,7 +100,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
|||||||
}, [hasSpecialView, viewMode])
|
}, [hasSpecialView, viewMode])
|
||||||
|
|
||||||
const [expandOverride, setExpandOverride] = useState(!codeCollapsible)
|
const [expandOverride, setExpandOverride] = useState(!codeCollapsible)
|
||||||
const [unwrapOverride, setUnwrapOverride] = useState(!codeWrappable)
|
const [wrapOverride, setWrapOverride] = useState(codeWrappable)
|
||||||
|
|
||||||
// 重置用户操作
|
// 重置用户操作
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -109,11 +109,11 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
|||||||
|
|
||||||
// 重置用户操作
|
// 重置用户操作
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUnwrapOverride(!codeWrappable)
|
setWrapOverride(codeWrappable)
|
||||||
}, [codeWrappable])
|
}, [codeWrappable])
|
||||||
|
|
||||||
const shouldExpand = useMemo(() => !codeCollapsible || expandOverride, [codeCollapsible, expandOverride])
|
const shouldExpand = useMemo(() => !codeCollapsible || expandOverride, [codeCollapsible, expandOverride])
|
||||||
const shouldUnwrap = useMemo(() => !codeWrappable || unwrapOverride, [codeWrappable, unwrapOverride])
|
const shouldWrap = useMemo(() => codeWrappable && wrapOverride, [codeWrappable, wrapOverride])
|
||||||
|
|
||||||
const [sourceScrollHeight, setSourceScrollHeight] = useState(0)
|
const [sourceScrollHeight, setSourceScrollHeight] = useState(0)
|
||||||
const expandable = useMemo(() => {
|
const expandable = useMemo(() => {
|
||||||
@ -225,9 +225,9 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
|||||||
// 源代码视图的自动换行按钮
|
// 源代码视图的自动换行按钮
|
||||||
useWrapTool({
|
useWrapTool({
|
||||||
enabled: !isInSpecialView,
|
enabled: !isInSpecialView,
|
||||||
unwrapped: shouldUnwrap,
|
wrapped: shouldWrap,
|
||||||
wrappable: codeWrappable,
|
wrappable: codeWrappable,
|
||||||
toggle: useCallback(() => setUnwrapOverride((prev) => !prev), []),
|
toggle: useCallback(() => setWrapOverride((prev) => !prev), []),
|
||||||
setTools
|
setTools
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -249,21 +249,22 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
|||||||
language={language}
|
language={language}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
onHeightChange={handleHeightChange}
|
onHeightChange={handleHeightChange}
|
||||||
|
maxHeight={`${MAX_COLLAPSED_CODE_HEIGHT}px`}
|
||||||
options={{ stream: true }}
|
options={{ stream: true }}
|
||||||
expanded={shouldExpand}
|
expanded={shouldExpand}
|
||||||
unwrapped={shouldUnwrap}
|
wrapped={shouldWrap}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<CodeViewer
|
<CodeViewer
|
||||||
className="source-view"
|
className="source-view"
|
||||||
language={language}
|
language={language}
|
||||||
expanded={shouldExpand}
|
expanded={shouldExpand}
|
||||||
unwrapped={shouldUnwrap}
|
wrapped={shouldWrap}
|
||||||
onHeightChange={handleHeightChange}>
|
onHeightChange={handleHeightChange}>
|
||||||
{children}
|
{children}
|
||||||
</CodeViewer>
|
</CodeViewer>
|
||||||
),
|
),
|
||||||
[children, codeEditor.enabled, handleHeightChange, language, onSave, shouldExpand, shouldUnwrap]
|
[children, codeEditor.enabled, handleHeightChange, language, onSave, shouldExpand, shouldWrap]
|
||||||
)
|
)
|
||||||
|
|
||||||
// 特殊视图组件映射
|
// 特殊视图组件映射
|
||||||
@ -370,9 +371,10 @@ const SplitViewWrapper = styled.div<{ $isSpecialView: boolean; $isSplitView: boo
|
|||||||
&:not(:has(+ [class*='Container'])) {
|
&:not(:has(+ [class*='Container'])) {
|
||||||
// 特殊视图的 header 会隐藏,所以全都使用圆角
|
// 特殊视图的 header 会隐藏,所以全都使用圆角
|
||||||
border-radius: ${(props) => (props.$isSpecialView ? '8px' : '0 0 8px 8px')};
|
border-radius: ${(props) => (props.$isSpecialView ? '8px' : '0 0 8px 8px')};
|
||||||
|
// FIXME: 滚动条边缘会溢出,可以考虑增加 padding,但是要保证代码主题颜色铺满容器。
|
||||||
|
// overflow: hidden;
|
||||||
.code-viewer {
|
.code-viewer {
|
||||||
border-radius: 0 0 8px 8px;
|
border-radius: inherit;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { MAX_COLLAPSED_CODE_HEIGHT } from '@renderer/config/constant'
|
|
||||||
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
|
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import CodeMirror, { Annotation, BasicSetupOptions, EditorView, Extension } from '@uiw/react-codemirror'
|
import CodeMirror, { Annotation, BasicSetupOptions, EditorView, Extension } from '@uiw/react-codemirror'
|
||||||
@ -15,39 +14,81 @@ export interface CodeEditorHandles {
|
|||||||
save?: () => void
|
save?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CodeEditorProps {
|
export interface CodeEditorProps {
|
||||||
ref?: React.RefObject<CodeEditorHandles | null>
|
ref?: React.RefObject<CodeEditorHandles | null>
|
||||||
|
/** Value used in controlled mode, e.g., code blocks. */
|
||||||
value: string
|
value: string
|
||||||
|
/** Placeholder when the editor content is empty. */
|
||||||
placeholder?: string | HTMLElement
|
placeholder?: string | HTMLElement
|
||||||
|
/** Code language, supports aliases. */
|
||||||
language: string
|
language: string
|
||||||
|
/** Fired when ref.save() is called or the save shortcut is triggered. */
|
||||||
onSave?: (newContent: string) => void
|
onSave?: (newContent: string) => void
|
||||||
|
/** Fired when the editor content changes. */
|
||||||
onChange?: (newContent: string) => void
|
onChange?: (newContent: string) => void
|
||||||
|
/** Fired when the editor loses focus. */
|
||||||
onBlur?: (newContent: string) => void
|
onBlur?: (newContent: string) => void
|
||||||
|
/** Fired when the editor height changes. */
|
||||||
onHeightChange?: (scrollHeight: number) => void
|
onHeightChange?: (scrollHeight: number) => void
|
||||||
|
/**
|
||||||
|
* Fixed editor height, not exceeding maxHeight.
|
||||||
|
* Only works when expanded is false.
|
||||||
|
*/
|
||||||
height?: string
|
height?: string
|
||||||
minHeight?: string
|
/**
|
||||||
|
* Maximum editor height.
|
||||||
|
* Only works when expanded is false.
|
||||||
|
*/
|
||||||
maxHeight?: string
|
maxHeight?: string
|
||||||
|
/** Minimum editor height. */
|
||||||
|
minHeight?: string
|
||||||
|
/** Font size that overrides the app setting. */
|
||||||
fontSize?: string
|
fontSize?: string
|
||||||
/** 用于覆写编辑器的某些设置 */
|
/** Editor options that extend BasicSetupOptions. */
|
||||||
options?: {
|
options?: {
|
||||||
stream?: boolean // 用于流式响应场景,默认 false
|
/**
|
||||||
|
* Whether to enable special treatment for stream response.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
stream?: boolean
|
||||||
|
/**
|
||||||
|
* Whether to enable linting.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
lint?: boolean
|
lint?: boolean
|
||||||
|
/**
|
||||||
|
* Whether to enable keymap.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
keymap?: boolean
|
keymap?: boolean
|
||||||
} & BasicSetupOptions
|
} & BasicSetupOptions
|
||||||
/** 用于追加 extensions */
|
/** Additional extensions for CodeMirror. */
|
||||||
extensions?: Extension[]
|
extensions?: Extension[]
|
||||||
/** 用于覆写编辑器的样式,会直接传给 CodeMirror 的 style 属性 */
|
/** Style overrides for the editor, passed directly to CodeMirror's style property. */
|
||||||
style?: React.CSSProperties
|
style?: React.CSSProperties
|
||||||
|
/** CSS class name appended to the default `code-editor` class. */
|
||||||
className?: string
|
className?: string
|
||||||
|
/**
|
||||||
|
* Whether the editor is editable.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
editable?: boolean
|
editable?: boolean
|
||||||
|
/**
|
||||||
|
* Whether the editor is expanded.
|
||||||
|
* If true, the height and maxHeight props are ignored.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
expanded?: boolean
|
expanded?: boolean
|
||||||
unwrapped?: boolean
|
/**
|
||||||
|
* Whether the code lines are wrapped.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
wrapped?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 源代码编辑器,基于 CodeMirror,封装了 ReactCodeMirror。
|
* A code editor component based on CodeMirror.
|
||||||
*
|
* This is a wrapper of ReactCodeMirror.
|
||||||
* 目前必须和 CodeToolbar 配合使用。
|
|
||||||
*/
|
*/
|
||||||
const CodeEditor = ({
|
const CodeEditor = ({
|
||||||
ref,
|
ref,
|
||||||
@ -59,8 +100,8 @@ const CodeEditor = ({
|
|||||||
onBlur,
|
onBlur,
|
||||||
onHeightChange,
|
onHeightChange,
|
||||||
height,
|
height,
|
||||||
minHeight,
|
|
||||||
maxHeight,
|
maxHeight,
|
||||||
|
minHeight,
|
||||||
fontSize,
|
fontSize,
|
||||||
options,
|
options,
|
||||||
extensions,
|
extensions,
|
||||||
@ -68,7 +109,7 @@ const CodeEditor = ({
|
|||||||
className,
|
className,
|
||||||
editable = true,
|
editable = true,
|
||||||
expanded = true,
|
expanded = true,
|
||||||
unwrapped = false
|
wrapped = true
|
||||||
}: CodeEditorProps) => {
|
}: CodeEditorProps) => {
|
||||||
const { fontSize: _fontSize, codeShowLineNumbers: _lineNumbers, codeEditor } = useSettings()
|
const { fontSize: _fontSize, codeShowLineNumbers: _lineNumbers, codeEditor } = useSettings()
|
||||||
const enableKeymap = useMemo(() => options?.keymap ?? codeEditor.keymap, [options?.keymap, codeEditor.keymap])
|
const enableKeymap = useMemo(() => options?.keymap ?? codeEditor.keymap, [options?.keymap, codeEditor.keymap])
|
||||||
@ -121,12 +162,12 @@ const CodeEditor = ({
|
|||||||
return [
|
return [
|
||||||
...(extensions ?? []),
|
...(extensions ?? []),
|
||||||
...langExtensions,
|
...langExtensions,
|
||||||
...(unwrapped ? [] : [EditorView.lineWrapping]),
|
...(wrapped ? [EditorView.lineWrapping] : []),
|
||||||
saveKeymapExtension,
|
saveKeymapExtension,
|
||||||
blurExtension,
|
blurExtension,
|
||||||
heightListenerExtension
|
heightListenerExtension
|
||||||
].flat()
|
].flat()
|
||||||
}, [extensions, langExtensions, unwrapped, saveKeymapExtension, blurExtension, heightListenerExtension])
|
}, [extensions, langExtensions, wrapped, saveKeymapExtension, blurExtension, heightListenerExtension])
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
save: handleSave
|
save: handleSave
|
||||||
@ -138,9 +179,9 @@ const CodeEditor = ({
|
|||||||
value={initialContent.current}
|
value={initialContent.current}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
width="100%"
|
width="100%"
|
||||||
height={height}
|
height={expanded ? undefined : height}
|
||||||
|
maxHeight={expanded ? undefined : maxHeight}
|
||||||
minHeight={minHeight}
|
minHeight={minHeight}
|
||||||
maxHeight={expanded ? 'none' : (maxHeight ?? `${MAX_COLLAPSED_CODE_HEIGHT}px`)}
|
|
||||||
editable={editable}
|
editable={editable}
|
||||||
// @ts-ignore 强制使用,见 react-codemirror 的 Example.tsx
|
// @ts-ignore 强制使用,见 react-codemirror 的 Example.tsx
|
||||||
theme={activeCmTheme}
|
theme={activeCmTheme}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ describe('useWrapTool', () => {
|
|||||||
const createMockProps = (overrides: Partial<Parameters<typeof useWrapTool>[0]> = {}) => {
|
const createMockProps = (overrides: Partial<Parameters<typeof useWrapTool>[0]> = {}) => {
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
unwrapped: false,
|
wrapped: true,
|
||||||
wrappable: true,
|
wrappable: true,
|
||||||
toggle: vi.fn(),
|
toggle: vi.fn(),
|
||||||
setTools: vi.fn()
|
setTools: vi.fn()
|
||||||
@ -90,8 +90,8 @@ describe('useWrapTool', () => {
|
|||||||
expect(mockRegisterTool).not.toHaveBeenCalled()
|
expect(mockRegisterTool).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should re-register tool when unwrapped changes', () => {
|
it('should re-register tool when wrapped changes', () => {
|
||||||
const props = createMockProps({ unwrapped: false })
|
const props = createMockProps({ wrapped: true })
|
||||||
const { rerender } = renderHook((hookProps) => useWrapTool(hookProps), {
|
const { rerender } = renderHook((hookProps) => useWrapTool(hookProps), {
|
||||||
initialProps: props
|
initialProps: props
|
||||||
})
|
})
|
||||||
@ -100,8 +100,8 @@ describe('useWrapTool', () => {
|
|||||||
const firstCall = mockRegisterTool.mock.calls[0][0]
|
const firstCall = mockRegisterTool.mock.calls[0][0]
|
||||||
expect(firstCall.tooltip).toBe('code_block.wrap.off')
|
expect(firstCall.tooltip).toBe('code_block.wrap.off')
|
||||||
|
|
||||||
// Change unwrapped to true and rerender
|
// Change wrapped to false and rerender
|
||||||
const newProps = { ...props, unwrapped: true }
|
const newProps = { ...props, wrapped: false }
|
||||||
rerender(newProps)
|
rerender(newProps)
|
||||||
|
|
||||||
expect(mockRegisterTool).toHaveBeenCalledTimes(2)
|
expect(mockRegisterTool).toHaveBeenCalledTimes(2)
|
||||||
|
|||||||
@ -5,13 +5,13 @@ import { useTranslation } from 'react-i18next'
|
|||||||
|
|
||||||
interface UseWrapToolProps {
|
interface UseWrapToolProps {
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
unwrapped?: boolean
|
wrapped?: boolean
|
||||||
wrappable?: boolean
|
wrappable?: boolean
|
||||||
toggle: () => void
|
toggle: () => void
|
||||||
setTools: React.Dispatch<React.SetStateAction<ActionTool[]>>
|
setTools: React.Dispatch<React.SetStateAction<ActionTool[]>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWrapTool = ({ enabled, unwrapped, wrappable, toggle, setTools }: UseWrapToolProps) => {
|
export const useWrapTool = ({ enabled, wrapped, wrappable, toggle, setTools }: UseWrapToolProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { registerTool, removeTool } = useToolManager(setTools)
|
const { registerTool, removeTool } = useToolManager(setTools)
|
||||||
|
|
||||||
@ -23,13 +23,13 @@ export const useWrapTool = ({ enabled, unwrapped, wrappable, toggle, setTools }:
|
|||||||
if (enabled) {
|
if (enabled) {
|
||||||
registerTool({
|
registerTool({
|
||||||
...TOOL_SPECS.wrap,
|
...TOOL_SPECS.wrap,
|
||||||
icon: unwrapped ? <WrapIcon className="tool-icon" /> : <UnWrapIcon className="tool-icon" />,
|
icon: wrapped ? <UnWrapIcon className="tool-icon" /> : <WrapIcon className="tool-icon" />,
|
||||||
tooltip: unwrapped ? t('code_block.wrap.on') : t('code_block.wrap.off'),
|
tooltip: wrapped ? t('code_block.wrap.off') : t('code_block.wrap.on'),
|
||||||
visible: () => wrappable ?? false,
|
visible: () => wrappable ?? false,
|
||||||
onClick: handleToggle
|
onClick: handleToggle
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => removeTool(TOOL_SPECS.wrap.id)
|
return () => removeTool(TOOL_SPECS.wrap.id)
|
||||||
}, [enabled, handleToggle, registerTool, removeTool, t, unwrapped, wrappable])
|
}, [enabled, handleToggle, registerTool, removeTool, t, wrapped, wrappable])
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ interface CodeViewerProps {
|
|||||||
language: string
|
language: string
|
||||||
children: string
|
children: string
|
||||||
expanded?: boolean
|
expanded?: boolean
|
||||||
unwrapped?: boolean
|
wrapped?: boolean
|
||||||
onHeightChange?: (scrollHeight: number) => void
|
onHeightChange?: (scrollHeight: number) => void
|
||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
@ -25,7 +25,7 @@ interface CodeViewerProps {
|
|||||||
* - 使用虚拟滚动和按需高亮,改善页面内有大量长代码块时的响应
|
* - 使用虚拟滚动和按需高亮,改善页面内有大量长代码块时的响应
|
||||||
* - 并发安全
|
* - 并发安全
|
||||||
*/
|
*/
|
||||||
const CodeViewer = ({ children, language, expanded, unwrapped, onHeightChange, className }: CodeViewerProps) => {
|
const CodeViewer = ({ children, language, expanded, wrapped, onHeightChange, className }: CodeViewerProps) => {
|
||||||
const { codeShowLineNumbers, fontSize } = useSettings()
|
const { codeShowLineNumbers, fontSize } = useSettings()
|
||||||
const { getShikiPreProperties, isShikiThemeDark } = useCodeStyle()
|
const { getShikiPreProperties, isShikiThemeDark } = useCodeStyle()
|
||||||
const shikiThemeRef = useRef<HTMLDivElement>(null)
|
const shikiThemeRef = useRef<HTMLDivElement>(null)
|
||||||
@ -108,7 +108,7 @@ const CodeViewer = ({ children, language, expanded, unwrapped, onHeightChange, c
|
|||||||
<ScrollContainer
|
<ScrollContainer
|
||||||
ref={scrollerRef}
|
ref={scrollerRef}
|
||||||
className="shiki-scroller"
|
className="shiki-scroller"
|
||||||
$wrap={!unwrapped}
|
$wrap={wrapped}
|
||||||
$expanded={expanded}
|
$expanded={expanded}
|
||||||
$lineHeight={estimateSize()}
|
$lineHeight={estimateSize()}
|
||||||
style={
|
style={
|
||||||
@ -257,6 +257,7 @@ const ScrollContainer = styled.div<{
|
|||||||
.line-content {
|
.line-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
|
white-space: pre;
|
||||||
* {
|
* {
|
||||||
white-space: ${(props) => (props.$wrap ? 'pre-wrap' : 'pre')};
|
white-space: ${(props) => (props.$wrap ? 'pre-wrap' : 'pre')};
|
||||||
overflow-wrap: ${(props) => (props.$wrap ? 'break-word' : 'normal')};
|
overflow-wrap: ${(props) => (props.$wrap ? 'break-word' : 'normal')};
|
||||||
|
|||||||
@ -132,8 +132,8 @@ const AssistantPromptSettings: React.FC<Props> = ({ assistant, updateAssistant }
|
|||||||
onBlur={onUpdate}
|
onBlur={onUpdate}
|
||||||
height="calc(80vh - 202px)"
|
height="calc(80vh - 202px)"
|
||||||
fontSize="var(--ant-font-size)"
|
fontSize="var(--ant-font-size)"
|
||||||
expanded
|
expanded={false}
|
||||||
unwrapped={false}
|
wrapped
|
||||||
options={{
|
options={{
|
||||||
autocompletion: false,
|
autocompletion: false,
|
||||||
keymap: true,
|
keymap: true,
|
||||||
|
|||||||
@ -338,8 +338,8 @@ const DisplaySettings: FC = () => {
|
|||||||
placeholder={t('settings.display.custom.css.placeholder')}
|
placeholder={t('settings.display.custom.css.placeholder')}
|
||||||
onChange={(value) => dispatch(setCustomCss(value))}
|
onChange={(value) => dispatch(setCustomCss(value))}
|
||||||
height="60vh"
|
height="60vh"
|
||||||
expanded
|
expanded={false}
|
||||||
unwrapped={false}
|
wrapped
|
||||||
options={{
|
options={{
|
||||||
autocompletion: true,
|
autocompletion: true,
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
|
|||||||
@ -296,9 +296,9 @@ const AddMcpServerModal: FC<AddMcpServerModalProps> = ({
|
|||||||
placeholder={initialJsonExample}
|
placeholder={initialJsonExample}
|
||||||
language="json"
|
language="json"
|
||||||
onChange={handleEditorChange}
|
onChange={handleEditorChange}
|
||||||
maxHeight="300px"
|
height="60vh"
|
||||||
expanded
|
expanded={false}
|
||||||
unwrapped={false}
|
wrapped
|
||||||
options={{
|
options={{
|
||||||
lint: true,
|
lint: true,
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
|
|||||||
@ -134,8 +134,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
language="json"
|
language="json"
|
||||||
onChange={(value) => setJsonConfig(value)}
|
onChange={(value) => setJsonConfig(value)}
|
||||||
height="60vh"
|
height="60vh"
|
||||||
expanded
|
expanded={false}
|
||||||
unwrapped={false}
|
wrapped
|
||||||
options={{
|
options={{
|
||||||
lint: true,
|
lint: true,
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
|
|||||||
@ -78,8 +78,9 @@ const PopupContainer: React.FC<Props> = ({ provider, resolve }) => {
|
|||||||
language="json"
|
language="json"
|
||||||
onChange={(value) => setHeaderText(value)}
|
onChange={(value) => setHeaderText(value)}
|
||||||
placeholder={`{\n "Header-Name": "Header-Value"\n}`}
|
placeholder={`{\n "Header-Name": "Header-Value"\n}`}
|
||||||
expanded
|
height="60vh"
|
||||||
unwrapped={false}
|
expanded={false}
|
||||||
|
wrapped
|
||||||
options={{
|
options={{
|
||||||
lint: true,
|
lint: true,
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user