Skip to content
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

Merged
merged 4 commits into from Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 33 additions & 0 deletions .dumi/pages/theme-editor/components/JSONEditor.tsx
@@ -0,0 +1,33 @@
import { JSONEditor as Editor, Mode, type JSONEditorPropsOptional } from 'vanilla-jsoneditor';
Copy link
Member

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 里来

Copy link
Contributor Author

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 里来

收到🫡

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;
78 changes: 76 additions & 2 deletions .dumi/pages/theme-editor/index.tsx
@@ -1,19 +1,27 @@
import React, { useEffect } from 'react';
import { isObject } from 'lodash';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个干掉吧,lodash 太大了,可以自己实现

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个干掉吧,lodash 太大了,可以自己实现

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 即可',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

将 JSON 复制到 ConfigProvider 的 theme 属性中套用主题。

editJsonContentTypeError: '主题 JSON 格式错误',
editSuccessfully: '编辑成功',
exportDesc: '将下面的 JSON 对象复制到 ConfigProvider 的 theme 属性中即可。',
saveSuccessfully: '保存成功',
},
Expand All @@ -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',
},
Expand Down Expand Up @@ -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: '{}',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

初始化的时候能不能让默认值是当前的配置,而不是空对象?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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>
Expand All @@ -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 }}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<Button onClick={handleEditConfig} icon={<EditOutlined />} style={{ marginRight: 8 }}>
<Button onClick={handleEditConfig} style={{ marginRight: 8 }}>

{locale.edit}
</Button>
<Button onClick={handleOutput} style={{ marginRight: 8 }}>
{locale.export}
</Button>
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是不是可以放进 devDependencies 里面?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是不是可以放进 devDependencies 里面?

应该不可以吧qwq

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该放 devDependencies 里

},
"devDependencies": {
"@ant-design/tools": "^16.1.0-alpha.2",
Expand Down