+
+ } style={{ marginRight: 8 }}>
+ {locale.upload}
+
+
From 5202c9733f57ee5abfb485772094b98d855aafbd Mon Sep 17 00:00:00 2001
From: BoyYangZai <2365539910@qq.com>
Date: Sun, 18 Dec 2022 20:45:01 +0800
Subject: [PATCH 2/4] verision 2
---
.../theme-editor/components/JSONEditor.tsx | 33 +++++
.dumi/pages/theme-editor/index.tsx | 116 +++++++++++-------
package.json | 3 +-
3 files changed, 109 insertions(+), 43 deletions(-)
create mode 100644 .dumi/pages/theme-editor/components/JSONEditor.tsx
diff --git a/.dumi/pages/theme-editor/components/JSONEditor.tsx b/.dumi/pages/theme-editor/components/JSONEditor.tsx
new file mode 100644
index 000000000000..28a71ee33b0e
--- /dev/null
+++ b/.dumi/pages/theme-editor/components/JSONEditor.tsx
@@ -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
;
+};
+
+export default JSONEditor;
diff --git a/.dumi/pages/theme-editor/index.tsx b/.dumi/pages/theme-editor/index.tsx
index 733fa8eb0412..5bb92e15c3f4 100644
--- a/.dumi/pages/theme-editor/index.tsx
+++ b/.dumi/pages/theme-editor/index.tsx
@@ -1,13 +1,15 @@
-import React, { useCallback, useEffect } from 'react';
+import { isObject } from 'lodash';
+import React, { useCallback, useEffect, useState } from 'react';
import { enUS, zhCN, ThemeEditor } from 'antd-token-previewer';
-import { Button, ConfigProvider, message, Modal, Typography, Upload, type UploadProps } from 'antd';
+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, UploadOutlined } from '@ant-design/icons';
-import isObject from 'lodash/isObject';
+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: {
@@ -15,9 +17,11 @@ const locales = {
save: '保存',
reset: '重置',
export: '导出',
- upload: '上传',
- uploadFileTypeError: '只允许上传 JSON 文件',
- uploadJsonContentTypeError: 'JSON 文件内容格式错误',
+ edit: '编辑',
+ editModelTitle: '编辑主题配置',
+ editTitle: '在下方编辑你的主题 JSON 即可',
+ editJsonContentTypeError: '主题 JSON 格式错误',
+ editSuccessfully: '编辑成功',
exportDesc: '将下面的 JSON 对象复制到 ConfigProvider 的 theme 属性中即可。',
saveSuccessfully: '保存成功',
},
@@ -26,9 +30,11 @@ const locales = {
save: 'Save',
reset: 'Reset',
export: 'Export',
- upload: 'Upload',
- uploadFileTypeError: 'Only JSON files can be uploaded',
- uploadJsonContentTypeError: 'The content format of the JSON file is incorrect',
+ 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',
},
@@ -110,36 +116,47 @@ const CustomTheme = () => {
setTheme({});
};
- const uploadJsonThemeFile = useCallback(async (file) => {
- if (file.type !== 'application/json') {
- message.error({
- content: locale.uploadFileTypeError,
- });
- return false;
- }
- const reader = new FileReader();
- reader.readAsText(file);
- reader.onload = () => {
- const uploadedThemeConfig = JSON.parse(reader.result as string);
- if (!isObject(uploadedThemeConfig)) {
- message.error({
- content: locale.uploadJsonContentTypeError,
- });
- return;
- }
- setTheme(uploadedThemeConfig);
- };
- }, []);
+ const [editModelOpen, setEditModelOpen] = useState
(false);
+ const [editThemeFormatRight, setEditThemeFormatRight] = useState(true);
+ const [content, setContent] = useState({
+ text: '{}',
+ });
- const uploadProps: UploadProps = {
- name: 'file',
- action: '',
- showUploadList: false,
- beforeUpload: (file) => {
- uploadJsonThemeFile(file);
- },
+ 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 (
@@ -154,11 +171,26 @@ const CustomTheme = () => {
{locale.title}
-
- } style={{ marginRight: 8 }}>
- {locale.upload}
-
-
+
+
+
+
} style={{ marginRight: 8 }}>
+ {locale.edit}
+
diff --git a/package.json b/package.json
index 6dcc816c1f49..5894a91c95dc 100644
--- a/package.json
+++ b/package.json
@@ -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"
},
"devDependencies": {
"@ant-design/tools": "^16.1.0-alpha.2",
From 344f6c506bddf02ceeec23de55aa0251750e4c1b Mon Sep 17 00:00:00 2001
From: BoyYangZai <2365539910@qq.com>
Date: Mon, 19 Dec 2022 01:02:33 +0800
Subject: [PATCH 3/4] =?UTF-8?q?=E7=A7=BB=E9=99=A4lodash=E3=80=81=E5=90=8C?=
=?UTF-8?q?=E6=AD=A5=E5=BD=93=E5=89=8DConfig?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.dumi/pages/theme-editor/components/utils.tsx | 4 ++
.dumi/pages/theme-editor/index.tsx | 37 ++++++++++++-------
2 files changed, 28 insertions(+), 13 deletions(-)
create mode 100644 .dumi/pages/theme-editor/components/utils.tsx
diff --git a/.dumi/pages/theme-editor/components/utils.tsx b/.dumi/pages/theme-editor/components/utils.tsx
new file mode 100644
index 000000000000..afc5450e5fbd
--- /dev/null
+++ b/.dumi/pages/theme-editor/components/utils.tsx
@@ -0,0 +1,4 @@
+/* eslint-disable import/prefer-default-export */
+export function isObject(target: any) {
+ return Object.prototype.toString.call(target) === '[object Object]';
+}
diff --git a/.dumi/pages/theme-editor/index.tsx b/.dumi/pages/theme-editor/index.tsx
index 5bb92e15c3f4..f071fc7daa44 100644
--- a/.dumi/pages/theme-editor/index.tsx
+++ b/.dumi/pages/theme-editor/index.tsx
@@ -1,4 +1,3 @@
-import { isObject } from 'lodash';
import React, { useCallback, useEffect, useState } from 'react';
import { enUS, zhCN, ThemeEditor } from 'antd-token-previewer';
import { Button, ConfigProvider, message, Modal, Typography } from 'antd';
@@ -7,9 +6,10 @@ import { Helmet } from 'dumi';
import { css } from '@emotion/react';
import CopyToClipboard from 'react-copy-to-clipboard';
import { CopyOutlined, EditOutlined } from '@ant-design/icons';
-import { type TextContent } from 'vanilla-jsoneditor';
+import type { JSONContent, TextContent } from 'vanilla-jsoneditor';
import useLocale from '../../hooks/useLocale';
import JSONEditor from './components/JSONEditor';
+import { isObject } from './components/utils';
const locales = {
cn: {
@@ -60,6 +60,13 @@ const CustomTheme = () => {
const [theme, setTheme] = React.useState
({});
+ const [editModelOpen, setEditModelOpen] = useState(false);
+ const [editThemeFormatRight, setEditThemeFormatRight] = useState(true);
+ const [themeConfigContent, setThemeConfigContent] = useState({
+ text: '{}',
+ json: undefined,
+ });
+
useEffect(() => {
const storedConfig = localStorage.getItem(ANT_DESIGN_V5_THEME_EDITOR_THEME);
if (storedConfig) {
@@ -67,6 +74,14 @@ const CustomTheme = () => {
}
}, []);
+ useEffect(() => {
+ if (editModelOpen === true) return;
+ setThemeConfigContent({
+ json: theme as any,
+ text: undefined,
+ });
+ }, [theme, editModelOpen]);
+
const styles = useStyle();
const handleSave = () => {
@@ -116,22 +131,16 @@ const CustomTheme = () => {
setTheme({});
};
- const [editModelOpen, setEditModelOpen] = useState(false);
- const [editThemeFormatRight, setEditThemeFormatRight] = useState(true);
- const [content, setContent] = useState({
- text: '{}',
- });
-
const handleEditConfig = () => {
setEditModelOpen(true);
};
const editModelClose = useCallback(() => {
setEditModelOpen(false);
- }, [content]);
+ }, [themeConfigContent]);
const handleEditConfigChange = (newcontent, preContent, status) => {
- setContent(newcontent);
+ setThemeConfigContent(newcontent);
if (
Array.isArray(status.contentErrors.validationErrors) &&
status.contentErrors.validationErrors.length === 0
@@ -147,7 +156,9 @@ const CustomTheme = () => {
message.error(locale.editJsonContentTypeError);
return;
}
- const themeConfig = JSON.parse(content.text);
+ const themeConfig = themeConfigContent.text
+ ? JSON.parse(themeConfigContent.text)
+ : themeConfigContent.json;
if (!isObject(themeConfig)) {
message.error(locale.editJsonContentTypeError);
return;
@@ -155,7 +166,7 @@ const CustomTheme = () => {
setTheme(themeConfig);
editModelClose();
messageApi.success(locale.editSuccessfully);
- }, [content]);
+ }, [themeConfigContent]);
return (
@@ -182,7 +193,7 @@ const CustomTheme = () => {
{locale.editTitle}
From bb2cfc0acc5bc26561da3a9958a296692754e734 Mon Sep 17 00:00:00 2001
From: BoyYangZai <2365539910@qq.com>
Date: Mon, 19 Dec 2022 14:55:59 +0800
Subject: [PATCH 4/4] remove export,add into devDependencies,add tool link
---
.dumi/pages/theme-editor/index.tsx | 54 ++----------------------------
docs/react/recommendation.zh-CN.md | 1 +
package.json | 4 +--
3 files changed, 6 insertions(+), 53 deletions(-)
diff --git a/.dumi/pages/theme-editor/index.tsx b/.dumi/pages/theme-editor/index.tsx
index f071fc7daa44..c651513a5547 100644
--- a/.dumi/pages/theme-editor/index.tsx
+++ b/.dumi/pages/theme-editor/index.tsx
@@ -4,8 +4,7 @@ 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, EditOutlined } from '@ant-design/icons';
+import { EditOutlined } from '@ant-design/icons';
import type { JSONContent, TextContent } from 'vanilla-jsoneditor';
import useLocale from '../../hooks/useLocale';
import JSONEditor from './components/JSONEditor';
@@ -16,26 +15,22 @@ const locales = {
title: '主题编辑器',
save: '保存',
reset: '重置',
- export: '导出',
- edit: '编辑',
+ edit: '代码',
editModelTitle: '编辑主题配置',
editTitle: '在下方编辑你的主题 JSON 即可',
editJsonContentTypeError: '主题 JSON 格式错误',
editSuccessfully: '编辑成功',
- exportDesc: '将下面的 JSON 对象复制到 ConfigProvider 的 theme 属性中即可。',
saveSuccessfully: '保存成功',
},
en: {
title: 'Theme Editor',
save: 'Save',
reset: 'Reset',
- export: 'Export',
- edit: 'Edit',
+ edit: 'Code',
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',
},
};
@@ -55,7 +50,6 @@ const ANT_DESIGN_V5_THEME_EDITOR_THEME = 'ant-design-v5-theme-editor-theme';
const CustomTheme = () => {
const [messageApi, contextHolder] = message.useMessage();
- const [modalApi, modalContextHolder] = Modal.useModal();
const [locale, lang] = useLocale(locales);
const [theme, setTheme] = React.useState
({});
@@ -89,44 +83,6 @@ const CustomTheme = () => {
messageApi.success(locale.saveSuccessfully);
};
- const onCopy = (text: string, result: boolean) => {
- if (result) {
- messageApi.success('Copy theme config successfully!');
- } else {
- messageApi.error('Copy failed, please try again.');
- }
- };
-
- const handleOutput = () => {
- modalApi.info({
- title: locale.export,
- width: 600,
- content: (
-
-
{locale.exportDesc}
-
-
- }
- style={{ position: 'absolute', right: 8, top: 8 }}
- />
-
- {JSON.stringify(theme, null, 2)}
-
-
- ),
- });
- };
-
const handleReset = () => {
setTheme({});
};
@@ -175,7 +131,6 @@ const CustomTheme = () => {
{contextHolder}
- {modalContextHolder}
@@ -202,9 +157,6 @@ const CustomTheme = () => {
} style={{ marginRight: 8 }}>
{locale.edit}
-
diff --git a/docs/react/recommendation.zh-CN.md b/docs/react/recommendation.zh-CN.md
index 835c57fabbbf..3a53d8db8f02 100644
--- a/docs/react/recommendation.zh-CN.md
+++ b/docs/react/recommendation.zh-CN.md
@@ -15,6 +15,7 @@ title: 社区精选组件
| 拖拽 | [dnd-kit](https://github.com/clauderic/dnd-kit) [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd/) [react-dnd](https://github.com/gaearon/react-dnd) [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc) |
| 代码编辑器 | [react-codemirror2](https://github.com/scniro/react-codemirror2) [react-monaco-editor](https://github.com/superRaytin/react-monaco-editor) |
| 富文本编辑器 | [react-quill](https://github.com/zenoamaro/react-quill) [braft-editor](https://github.com/margox/braft-editor) |
+| JSON 编辑器 | [vanilla-jsoneditor](https://github.com/josdejong/svelte-jsoneditor) |
| JSON 显示器 | [react-json-view](https://github.com/mac-s-g/react-json-view) |
| 拾色器 | [react-colorful](https://github.com/omgovich/react-colorful) [react-color](http://casesandberg.github.io/react-color/) |
| 响应式 | [react-responsive](https://github.com/contra/react-responsive) [react-media](https://github.com/ReactTraining/react-media) |
diff --git a/package.json b/package.json
index 5894a91c95dc..022a8c767302 100644
--- a/package.json
+++ b/package.json
@@ -154,8 +154,7 @@
"rc-util": "^5.25.2",
"scroll-into-view-if-needed": "^3.0.3",
"shallowequal": "^1.1.0",
- "throttle-debounce": "^5.0.0",
- "vanilla-jsoneditor": "^0.11.4"
+ "throttle-debounce": "^5.0.0"
},
"devDependencies": {
"@ant-design/tools": "^16.1.0-alpha.2",
@@ -285,6 +284,7 @@
"ts-node": "^10.8.2",
"typedoc": "^0.23.21",
"typescript": "~4.9.3",
+ "vanilla-jsoneditor": "^0.11.4",
"webpack-bundle-analyzer": "^4.1.0",
"xhr-mock": "^2.4.1",
"yaml-front-matter": "^4.0.0"