New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add Theme Config Editor #39621
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { JSONEditor as Editor, Mode, type JSONEditorPropsOptional } from 'vanilla-jsoneditor'; | ||
import React from 'react'; | ||
|
||
const JSONEditor = (props: JSONEditorPropsOptional) => { | ||
const refContainer = React.useRef(null); | ||
const refEditor = React.useRef(null); | ||
|
||
React.useEffect(() => { | ||
refEditor.current = new Editor({ | ||
target: refContainer.current, | ||
props: { | ||
mode: Mode.text, | ||
}, | ||
}); | ||
|
||
return () => { | ||
if (refEditor.current) { | ||
refEditor.current.destroy(); | ||
refEditor.current = null; | ||
} | ||
}; | ||
}, []); | ||
|
||
React.useEffect(() => { | ||
if (refEditor.current) { | ||
refEditor.current.updateProps(props); | ||
} | ||
}, [props]); | ||
|
||
return <div className="vanilla-jsoneditor-react" ref={refContainer} />; | ||
}; | ||
|
||
export default JSONEditor; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,19 +1,27 @@ | ||||||
import React, { useEffect } from 'react'; | ||||||
import { isObject } from 'lodash'; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个干掉吧,lodash 太大了,可以自己实现 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
ok |
||||||
import React, { useCallback, useEffect, useState } from 'react'; | ||||||
import { enUS, zhCN, ThemeEditor } from 'antd-token-previewer'; | ||||||
import { Button, ConfigProvider, message, Modal, Typography } from 'antd'; | ||||||
import type { ThemeConfig } from 'antd/es/config-provider/context'; | ||||||
import { Helmet } from 'dumi'; | ||||||
import { css } from '@emotion/react'; | ||||||
import CopyToClipboard from 'react-copy-to-clipboard'; | ||||||
import { CopyOutlined } from '@ant-design/icons'; | ||||||
import { CopyOutlined, EditOutlined } from '@ant-design/icons'; | ||||||
import { type TextContent } from 'vanilla-jsoneditor'; | ||||||
import useLocale from '../../hooks/useLocale'; | ||||||
import JSONEditor from './components/JSONEditor'; | ||||||
|
||||||
const locales = { | ||||||
cn: { | ||||||
title: '主题编辑器', | ||||||
save: '保存', | ||||||
reset: '重置', | ||||||
export: '导出', | ||||||
edit: '编辑', | ||||||
editModelTitle: '编辑主题配置', | ||||||
editTitle: '在下方编辑你的主题 JSON 即可', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 将 JSON 复制到 ConfigProvider 的 theme 属性中套用主题。 |
||||||
editJsonContentTypeError: '主题 JSON 格式错误', | ||||||
editSuccessfully: '编辑成功', | ||||||
exportDesc: '将下面的 JSON 对象复制到 ConfigProvider 的 theme 属性中即可。', | ||||||
saveSuccessfully: '保存成功', | ||||||
}, | ||||||
|
@@ -22,6 +30,11 @@ const locales = { | |||||
save: 'Save', | ||||||
reset: 'Reset', | ||||||
export: 'Export', | ||||||
edit: 'Edit', | ||||||
editModelTitle: 'edit Theme Config', | ||||||
editTitle: 'Edit your theme JSON below', | ||||||
editJsonContentTypeError: 'The theme of the JSON format is incorrect', | ||||||
editSuccessfully: 'Edited successfully', | ||||||
exportDesc: 'Copy the following JSON object to the theme prop of ConfigProvider.', | ||||||
saveSuccessfully: 'Saved successfully', | ||||||
}, | ||||||
|
@@ -103,6 +116,47 @@ const CustomTheme = () => { | |||||
setTheme({}); | ||||||
}; | ||||||
|
||||||
const [editModelOpen, setEditModelOpen] = useState<boolean>(false); | ||||||
const [editThemeFormatRight, setEditThemeFormatRight] = useState<boolean>(true); | ||||||
const [content, setContent] = useState<TextContent>({ | ||||||
text: '{}', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 初始化的时候能不能让默认值是当前的配置,而不是空对象? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
可以 |
||||||
}); | ||||||
|
||||||
const handleEditConfig = () => { | ||||||
setEditModelOpen(true); | ||||||
}; | ||||||
|
||||||
const editModelClose = useCallback(() => { | ||||||
setEditModelOpen(false); | ||||||
}, [content]); | ||||||
|
||||||
const handleEditConfigChange = (newcontent, preContent, status) => { | ||||||
setContent(newcontent); | ||||||
if ( | ||||||
Array.isArray(status.contentErrors.validationErrors) && | ||||||
status.contentErrors.validationErrors.length === 0 | ||||||
) { | ||||||
setEditThemeFormatRight(true); | ||||||
} else { | ||||||
setEditThemeFormatRight(false); | ||||||
} | ||||||
}; | ||||||
|
||||||
const editSave = useCallback(() => { | ||||||
if (!editThemeFormatRight) { | ||||||
message.error(locale.editJsonContentTypeError); | ||||||
return; | ||||||
} | ||||||
const themeConfig = JSON.parse(content.text); | ||||||
if (!isObject(themeConfig)) { | ||||||
message.error(locale.editJsonContentTypeError); | ||||||
return; | ||||||
} | ||||||
setTheme(themeConfig); | ||||||
editModelClose(); | ||||||
messageApi.success(locale.editSuccessfully); | ||||||
}, [content]); | ||||||
|
||||||
return ( | ||||||
<div> | ||||||
<Helmet> | ||||||
|
@@ -117,6 +171,26 @@ const CustomTheme = () => { | |||||
{locale.title} | ||||||
</Typography.Title> | ||||||
<div> | ||||||
<Modal | ||||||
open={editModelOpen} | ||||||
title={locale.editModelTitle} | ||||||
width={600} | ||||||
okText={locale.save} | ||||||
onOk={editSave} | ||||||
onCancel={editModelClose} | ||||||
> | ||||||
<div> | ||||||
<div style={{ color: 'rgba(0,0,0,0.65)' }}>{locale.editTitle}</div> | ||||||
<JSONEditor | ||||||
content={content} | ||||||
onChange={handleEditConfigChange} | ||||||
mainMenuBar={false} | ||||||
/> | ||||||
</div> | ||||||
</Modal> | ||||||
<Button onClick={handleEditConfig} icon={<EditOutlined />} style={{ marginRight: 8 }}> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
{locale.edit} | ||||||
</Button> | ||||||
<Button onClick={handleOutput} style={{ marginRight: 8 }}> | ||||||
{locale.export} | ||||||
</Button> | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -154,7 +154,8 @@ | |
"rc-util": "^5.25.2", | ||
"scroll-into-view-if-needed": "^3.0.3", | ||
"shallowequal": "^1.1.0", | ||
"throttle-debounce": "^5.0.0" | ||
"throttle-debounce": "^5.0.0", | ||
"vanilla-jsoneditor": "^0.11.4" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个是不是可以放进 devDependencies 里面? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
应该不可以吧qwq There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 应该放 devDependencies 里 |
||
}, | ||
"devDependencies": { | ||
"@ant-design/tools": "^16.1.0-alpha.2", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vanilla-jsoneditor 可以加到 https://ant.design/docs/react/recommendation-cn 里来
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
收到🫡