@fe-free/core 1.2.4 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/package.json +4 -4
- package/src/button/button.stories.ts +7 -2
- package/src/button/index.tsx +1 -1
- package/src/crud/crud.stories.tsx +384 -0
- package/src/crud/crud.tsx +42 -102
- package/src/crud/crud_delete.tsx +19 -23
- package/src/crud/crud_detail.tsx +6 -6
- package/src/crud/demo/data.tsx +6 -6
- package/src/crud/index.tsx +2 -2
- package/src/crud/types.tsx +98 -0
- package/src/crud/use_row_selection.tsx +84 -0
- package/src/editor_javascript/{index.md → editor_javascript.stories.tsx} +24 -38
- package/src/editor_javascript/index.tsx +2 -1
- package/src/editor_json/{index.md → editor_json.stories.tsx} +42 -67
- package/src/editor_json/index.tsx +1 -0
- package/src/editor_logs/editor_logs.stories.tsx +47 -0
- package/src/editor_logs/index.tsx +4 -3
- package/src/editor_markdown/editor_markdown.stories.tsx +32 -0
- package/src/editor_markdown/index.tsx +1 -0
- package/src/form/form.stories.tsx +65 -0
- package/src/index.ts +13 -9
- package/src/table/index.tsx +3 -3
- package/src/table/table.stories.tsx +80 -0
- package/src/tailwindcss.stories.tsx +1 -1
- package/src/value_type_map/{index.md → value_type_map.stories.tsx} +22 -52
- package/src/crud/demo/index.tsx +0 -342
- package/src/crud/index.md +0 -158
- package/src/editor_logs/index.md +0 -48
- package/src/editor_markdown/index.md +0 -40
- package/src/form/index.md +0 -96
- package/src/table/index.md +0 -89
package/src/crud/crud_delete.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
1
|
import { Modal } from 'antd';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
3
|
|
|
4
4
|
interface Params {
|
|
5
5
|
name: string;
|
|
@@ -7,18 +7,24 @@ interface Params {
|
|
|
7
7
|
operateText?: string;
|
|
8
8
|
onDelete: () => Promise<any>;
|
|
9
9
|
}
|
|
10
|
+
|
|
10
11
|
function useDelete(params: Params) {
|
|
11
12
|
const { name, desc, onDelete } = params;
|
|
12
13
|
|
|
13
|
-
const doDelete = useCallback(() => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
const doDelete = useCallback(async () => {
|
|
15
|
+
await new Promise((resolve) => {
|
|
16
|
+
Modal.confirm({
|
|
17
|
+
title: `确认删除 “${name}” 吗?`,
|
|
18
|
+
content: desc || '删除后不可恢复,请谨慎操作',
|
|
19
|
+
okText: '确定',
|
|
20
|
+
cancelText: '取消',
|
|
21
|
+
onOk: () => {
|
|
22
|
+
resolve(onDelete());
|
|
23
|
+
},
|
|
24
|
+
onCancel: () => {
|
|
25
|
+
resolve(undefined);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
22
28
|
});
|
|
23
29
|
}, [name, desc, onDelete]);
|
|
24
30
|
|
|
@@ -29,23 +35,13 @@ function useDelete(params: Params) {
|
|
|
29
35
|
|
|
30
36
|
function OperateDelete(props: Params) {
|
|
31
37
|
const { name, desc, onDelete, operateText } = props;
|
|
32
|
-
const
|
|
33
|
-
Modal.confirm({
|
|
34
|
-
title: `确认删除 “${name}” 吗?`,
|
|
35
|
-
content: desc || '删除后不可恢复,请谨慎操作',
|
|
36
|
-
okText: '确定',
|
|
37
|
-
cancelText: '取消',
|
|
38
|
-
onOk: () => {
|
|
39
|
-
onDelete();
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
}, [name, desc, onDelete]);
|
|
38
|
+
const { doDelete } = useDelete({ name, desc, onDelete, operateText });
|
|
43
39
|
|
|
44
40
|
return (
|
|
45
|
-
<a style={{ color: 'red' }} onClick={
|
|
41
|
+
<a style={{ color: 'red' }} onClick={doDelete}>
|
|
46
42
|
{operateText || '删除'}
|
|
47
43
|
</a>
|
|
48
44
|
);
|
|
49
45
|
}
|
|
50
46
|
|
|
51
|
-
export {
|
|
47
|
+
export { OperateDelete, useDelete };
|
package/src/crud/crud_detail.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { message, Spin } from 'antd';
|
|
2
1
|
import { DrawerForm, ProForm } from '@ant-design/pro-components';
|
|
2
|
+
import { message, Spin } from 'antd';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import { isString } from 'lodash-es';
|
|
3
5
|
import { useCallback, useMemo, useState } from 'react';
|
|
4
6
|
import type { CRUDProps } from './crud';
|
|
5
|
-
import { isString } from 'lodash-es';
|
|
6
|
-
import classNames from 'classnames';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* create 创建
|
|
@@ -100,13 +100,13 @@ function CRUDDetail(props: CRUDDetailProps) {
|
|
|
100
100
|
return true;
|
|
101
101
|
}
|
|
102
102
|
} catch (e) {
|
|
103
|
-
// 由于 onFinish 吃掉了 error
|
|
103
|
+
// 由于 onFinish 吃掉了 error,所以这里自行抛出到全局
|
|
104
104
|
setTimeout(() => {
|
|
105
105
|
throw e;
|
|
106
106
|
}, 10);
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
|
-
[action, requestCreateByValues, requestUpdateById, onSuccess, createProps, id, updateProps]
|
|
109
|
+
[action, requestCreateByValues, requestUpdateById, onSuccess, createProps, id, updateProps],
|
|
110
110
|
);
|
|
111
111
|
|
|
112
112
|
const handleOpenChange = useCallback(
|
|
@@ -132,7 +132,7 @@ function CRUDDetail(props: CRUDDetailProps) {
|
|
|
132
132
|
|
|
133
133
|
return;
|
|
134
134
|
},
|
|
135
|
-
[form, id, requestGetByRecord, record]
|
|
135
|
+
[form, id, requestGetByRecord, record],
|
|
136
136
|
);
|
|
137
137
|
|
|
138
138
|
const children = useMemo(() => {
|
package/src/crud/demo/data.tsx
CHANGED
|
@@ -43,7 +43,7 @@ function makeData(count) {
|
|
|
43
43
|
|
|
44
44
|
return {
|
|
45
45
|
id: `${id}`,
|
|
46
|
-
name:
|
|
46
|
+
name: `这是名字这是名字这是名字这是名字这是名字 ${id}`,
|
|
47
47
|
city,
|
|
48
48
|
area,
|
|
49
49
|
level: randomLevel(),
|
|
@@ -131,14 +131,14 @@ function fakeRequestSchool() {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export {
|
|
134
|
+
fakeCreate,
|
|
134
135
|
fakeData,
|
|
135
|
-
levels,
|
|
136
|
-
fakeRequest,
|
|
137
136
|
fakeDeleteByRecord,
|
|
138
137
|
fakeGetByRecord,
|
|
139
|
-
|
|
140
|
-
fakeUpdateById,
|
|
141
|
-
fakeRequestCity,
|
|
138
|
+
fakeRequest,
|
|
142
139
|
fakeRequestArea,
|
|
140
|
+
fakeRequestCity,
|
|
143
141
|
fakeRequestSchool,
|
|
142
|
+
fakeUpdateById,
|
|
143
|
+
levels,
|
|
144
144
|
};
|
package/src/crud/index.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CRUD } from './crud';
|
|
2
|
-
export
|
|
2
|
+
export { OperateDelete, useDelete } from './crud_delete';
|
|
3
3
|
export { CRUDDetail } from './crud_detail';
|
|
4
4
|
export type { CRUDDetailProps } from './crud_detail';
|
|
5
|
-
export {
|
|
5
|
+
export type { CRUDMethods, CRUDProps } from './types';
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { ActionType, ProFormInstance } from '@ant-design/pro-components';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { TableProps } from '../table';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* create 创建
|
|
7
|
+
* read 查看
|
|
8
|
+
* read_detail 详情页查看
|
|
9
|
+
* update 编辑
|
|
10
|
+
* delete 删除
|
|
11
|
+
*/
|
|
12
|
+
type CrudAction = 'create' | 'read' | 'read_detail' | 'update' | 'delete';
|
|
13
|
+
|
|
14
|
+
interface CRUDProps<
|
|
15
|
+
DataSource extends Record<string, any> = any,
|
|
16
|
+
Key extends string | number = string,
|
|
17
|
+
> {
|
|
18
|
+
actions: CrudAction[];
|
|
19
|
+
|
|
20
|
+
/** 新建按钮,默认新建 */
|
|
21
|
+
createButton?: ReactNode;
|
|
22
|
+
|
|
23
|
+
/** 表格相关 */
|
|
24
|
+
tableProps: TableProps<DataSource>;
|
|
25
|
+
operateColumnProps?: {
|
|
26
|
+
width?: number;
|
|
27
|
+
/** 扩展操作区域,再其他操作之前 */
|
|
28
|
+
moreOperator?: (record: DataSource) => ReactNode;
|
|
29
|
+
/** 扩展操作区域,在其他操作之后 */
|
|
30
|
+
moreOperatorAfter?: (record: DataSource) => ReactNode;
|
|
31
|
+
};
|
|
32
|
+
readProps?: {
|
|
33
|
+
/** 文本 */
|
|
34
|
+
operateText?: string;
|
|
35
|
+
/** 打开方式, action 为 read_detail 有效 */
|
|
36
|
+
target?: '_blank';
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** 删除接口 */
|
|
40
|
+
requestDeleteByRecord?: (record: DataSource) => Promise<any>;
|
|
41
|
+
/** 删除相关 */
|
|
42
|
+
deleteProps?: {
|
|
43
|
+
/** 显示名称索引 */
|
|
44
|
+
nameIndex: keyof DataSource;
|
|
45
|
+
/** 删除确认描述 */
|
|
46
|
+
desc?: string;
|
|
47
|
+
/** 文本 */
|
|
48
|
+
operateText?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** 弹窗表单 */
|
|
52
|
+
detailForm?: (formProps: { readonly: boolean }, info: { action: CrudAction }) => ReactNode;
|
|
53
|
+
/** detailForm 的 formRef */
|
|
54
|
+
detailFormInstance?: ProFormInstance;
|
|
55
|
+
|
|
56
|
+
/** 新增接口 */
|
|
57
|
+
requestCreateByValues?: (values: Partial<DataSource>) => Promise<any>;
|
|
58
|
+
createProps?: {
|
|
59
|
+
/** 成功文案 */
|
|
60
|
+
successText?: string | (() => string);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** 更新接口 */
|
|
64
|
+
requestUpdateByValues?: (values: Partial<DataSource>) => Promise<any>;
|
|
65
|
+
/** @deprecated 请使用 requestUpdateByValues 替代 */
|
|
66
|
+
requestUpdateById?: (values: Partial<DataSource>) => Promise<any>;
|
|
67
|
+
updateProps?: {
|
|
68
|
+
/** 文本 */
|
|
69
|
+
operateText?: string;
|
|
70
|
+
/** 成功文案 */
|
|
71
|
+
successText?: string | (() => string);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/** 获取详情接口 */
|
|
75
|
+
requestGetByRecord?: (record: DataSource) => Promise<any>;
|
|
76
|
+
|
|
77
|
+
/** 跳转到详情的索引 ,默认 id */
|
|
78
|
+
detailIdIndex?: string;
|
|
79
|
+
|
|
80
|
+
/** 批量操作 */
|
|
81
|
+
batchActions?: {
|
|
82
|
+
/** 按钮文本 */
|
|
83
|
+
btnText: string;
|
|
84
|
+
/** 红色,且有确认框 */
|
|
85
|
+
danger?: boolean;
|
|
86
|
+
/** 批量操作接口 */
|
|
87
|
+
onClick: (
|
|
88
|
+
event: React.MouseEvent<HTMLElement>,
|
|
89
|
+
options: { selectedRowKeys: Key[]; selectedRows: DataSource[] },
|
|
90
|
+
) => Promise<any>;
|
|
91
|
+
}[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface CRUDMethods {
|
|
95
|
+
getActionRef: () => React.MutableRefObject<ActionType | undefined>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export type { CRUDMethods, CRUDProps };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Modal } from 'antd';
|
|
2
|
+
import { useCallback, useMemo } from 'react';
|
|
3
|
+
import { LoadingButton } from '../button';
|
|
4
|
+
import type { CRUDProps } from './types';
|
|
5
|
+
|
|
6
|
+
function useRowSelection<
|
|
7
|
+
DataSource extends Record<string, any> = any,
|
|
8
|
+
Key extends string | number = string,
|
|
9
|
+
>({ batchActions }: { batchActions?: CRUDProps<DataSource, Key>['batchActions'] }) {
|
|
10
|
+
const rowSelection = useMemo(() => ({}), []);
|
|
11
|
+
|
|
12
|
+
const tableAlertRender = useCallback(({ selectedRowKeys, onCleanSelected }) => {
|
|
13
|
+
return (
|
|
14
|
+
<div>
|
|
15
|
+
<span>
|
|
16
|
+
已选 {selectedRowKeys.length} 项
|
|
17
|
+
<a style={{ marginInlineStart: 8 }} onClick={onCleanSelected}>
|
|
18
|
+
取消选择
|
|
19
|
+
</a>
|
|
20
|
+
</span>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}, []);
|
|
24
|
+
|
|
25
|
+
const tableAlertOptionRender = useCallback(
|
|
26
|
+
({ selectedRowKeys, selectedRows }) => {
|
|
27
|
+
return (
|
|
28
|
+
<div className="flex gap-2 items-center">
|
|
29
|
+
{batchActions?.map((action) => (
|
|
30
|
+
<LoadingButton
|
|
31
|
+
key={action.btnText}
|
|
32
|
+
type="link"
|
|
33
|
+
danger={action.danger}
|
|
34
|
+
onClick={async (event) => {
|
|
35
|
+
if (action.danger) {
|
|
36
|
+
await new Promise((resolve) => {
|
|
37
|
+
Modal.confirm({
|
|
38
|
+
title: `确定要执行 ${action.btnText} 吗?`,
|
|
39
|
+
onOk: () => {
|
|
40
|
+
resolve(
|
|
41
|
+
action.onClick(event, {
|
|
42
|
+
selectedRowKeys,
|
|
43
|
+
selectedRows,
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
onCancel: () => {
|
|
48
|
+
resolve(undefined);
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
} else {
|
|
53
|
+
await action.onClick(event, {
|
|
54
|
+
selectedRowKeys,
|
|
55
|
+
selectedRows,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
{action.btnText}
|
|
61
|
+
</LoadingButton>
|
|
62
|
+
))}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
},
|
|
66
|
+
[batchActions],
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
if (!batchActions || batchActions.length === 0) {
|
|
70
|
+
return {
|
|
71
|
+
rowSelection: undefined,
|
|
72
|
+
tableAlertRender: undefined,
|
|
73
|
+
tableAlertOptionRender: undefined,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
rowSelection,
|
|
79
|
+
tableAlertRender,
|
|
80
|
+
tableAlertOptionRender,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { useRowSelection };
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# EditorJavascript
|
|
7
|
-
|
|
8
|
-
## 代码演示
|
|
1
|
+
import { EditorJavascript } from '@fe-free/core';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { useState } from 'react';
|
|
9
4
|
|
|
10
|
-
|
|
5
|
+
const meta: Meta<typeof EditorJavascript> = {
|
|
6
|
+
title: '@fe-free/core/EditorJavascript',
|
|
7
|
+
component: EditorJavascript,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
};
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import { EditorJavascript } from '@fe-free/core';
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof EditorJavascript>;
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
// 常规示例
|
|
15
|
+
const BasicDemo = () => {
|
|
17
16
|
const [value, setValue] = useState(
|
|
18
17
|
`const name = 'world';
|
|
19
18
|
console.log('hello', name);
|
|
20
|
-
|
|
19
|
+
`,
|
|
21
20
|
);
|
|
22
21
|
|
|
23
22
|
return (
|
|
@@ -25,22 +24,18 @@ console.log('hello', name);
|
|
|
25
24
|
<EditorJavascript value={value} onChange={setValue} />
|
|
26
25
|
</div>
|
|
27
26
|
);
|
|
28
|
-
}
|
|
27
|
+
};
|
|
29
28
|
|
|
30
|
-
export
|
|
31
|
-
|
|
29
|
+
export const Basic: Story = {
|
|
30
|
+
render: () => <BasicDemo />,
|
|
31
|
+
};
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```tsx
|
|
36
|
-
import { useState } from 'react';
|
|
37
|
-
import { EditorJavascript } from '@fe-free/core';
|
|
38
|
-
|
|
39
|
-
function Demo() {
|
|
33
|
+
// readonly 示例
|
|
34
|
+
const ReadonlyDemo = () => {
|
|
40
35
|
const [value, setValue] = useState(
|
|
41
36
|
`const name = 'world';
|
|
42
37
|
console.log('hello', name);
|
|
43
|
-
|
|
38
|
+
`,
|
|
44
39
|
);
|
|
45
40
|
|
|
46
41
|
return (
|
|
@@ -48,17 +43,8 @@ console.log('hello', name);
|
|
|
48
43
|
<EditorJavascript value={value} onChange={setValue} readonly />
|
|
49
44
|
</div>
|
|
50
45
|
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export default Demo;
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## API
|
|
46
|
+
};
|
|
57
47
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
onChange: (value: string, event?: any) => void;
|
|
62
|
-
readonly?: boolean;
|
|
63
|
-
}
|
|
64
|
-
```
|
|
48
|
+
export const Readonly: Story = {
|
|
49
|
+
render: () => <ReadonlyDemo />,
|
|
50
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import AceEditor from 'react-ace';
|
|
2
2
|
|
|
3
|
+
import 'ace-builds/src-noconflict/ext-language_tools';
|
|
3
4
|
import 'ace-builds/src-noconflict/mode-javascript';
|
|
4
5
|
import 'ace-builds/src-noconflict/theme-monokai';
|
|
5
|
-
import 'ace-builds/src-noconflict/ext-language_tools';
|
|
6
6
|
|
|
7
7
|
const fullStyle = { width: '100%', height: '100%' };
|
|
8
8
|
|
|
@@ -34,3 +34,4 @@ function EditorJavascript({ value, onChange, readonly }: EditorJavascriptProps)
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export { EditorJavascript };
|
|
37
|
+
export type { EditorJavascriptProps };
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# EditorJSON
|
|
7
|
-
|
|
8
|
-
## 代码演示
|
|
1
|
+
import { EditorJSON } from '@fe-free/core';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { useState } from 'react';
|
|
9
4
|
|
|
10
|
-
|
|
5
|
+
const meta: Meta<typeof EditorJSON> = {
|
|
6
|
+
title: '@fe-free/core/EditorJSON',
|
|
7
|
+
component: EditorJSON,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
};
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import { EditorJSON } from '@fe-free/core';
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof EditorJSON>;
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
// 基础示例
|
|
15
|
+
const BasicDemo = () => {
|
|
17
16
|
const [value, setValue] = useState(
|
|
18
17
|
JSON.stringify(
|
|
19
18
|
{
|
|
20
19
|
name: 'world',
|
|
21
20
|
},
|
|
22
21
|
null,
|
|
23
|
-
2
|
|
24
|
-
)
|
|
22
|
+
2,
|
|
23
|
+
),
|
|
25
24
|
);
|
|
26
25
|
|
|
27
26
|
return (
|
|
@@ -29,26 +28,22 @@ function Demo() {
|
|
|
29
28
|
<EditorJSON value={value} onChange={setValue} />
|
|
30
29
|
</div>
|
|
31
30
|
);
|
|
32
|
-
}
|
|
31
|
+
};
|
|
33
32
|
|
|
34
|
-
export
|
|
35
|
-
|
|
33
|
+
export const Basic: Story = {
|
|
34
|
+
render: () => <BasicDemo />,
|
|
35
|
+
};
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```tsx
|
|
40
|
-
import { useState } from 'react';
|
|
41
|
-
import { EditorJSON } from '@fe-free/core';
|
|
42
|
-
|
|
43
|
-
function Demo() {
|
|
37
|
+
// 只读模式
|
|
38
|
+
const ReadonlyDemo = () => {
|
|
44
39
|
const [value, setValue] = useState(
|
|
45
40
|
JSON.stringify(
|
|
46
41
|
{
|
|
47
42
|
name: 'world',
|
|
48
43
|
},
|
|
49
44
|
null,
|
|
50
|
-
2
|
|
51
|
-
)
|
|
45
|
+
2,
|
|
46
|
+
),
|
|
52
47
|
);
|
|
53
48
|
|
|
54
49
|
return (
|
|
@@ -56,26 +51,22 @@ function Demo() {
|
|
|
56
51
|
<EditorJSON value={value} onChange={setValue} readonly />
|
|
57
52
|
</div>
|
|
58
53
|
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export default Demo;
|
|
62
|
-
```
|
|
54
|
+
};
|
|
63
55
|
|
|
64
|
-
|
|
56
|
+
export const Readonly: Story = {
|
|
57
|
+
render: () => <ReadonlyDemo />,
|
|
58
|
+
};
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
import { EditorJSON } from '@fe-free/core';
|
|
69
|
-
|
|
70
|
-
function Demo() {
|
|
60
|
+
// 树形模式
|
|
61
|
+
const TreeModeDemo = () => {
|
|
71
62
|
const [value, setValue] = useState(
|
|
72
63
|
JSON.stringify(
|
|
73
64
|
{
|
|
74
65
|
name: 'world',
|
|
75
66
|
},
|
|
76
67
|
null,
|
|
77
|
-
2
|
|
78
|
-
)
|
|
68
|
+
2,
|
|
69
|
+
),
|
|
79
70
|
);
|
|
80
71
|
|
|
81
72
|
return (
|
|
@@ -83,26 +74,22 @@ function Demo() {
|
|
|
83
74
|
<EditorJSON value={value} onChange={setValue} mode="tree" readonly />
|
|
84
75
|
</div>
|
|
85
76
|
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export default Demo;
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### readonly mainMenuBar mode
|
|
77
|
+
};
|
|
92
78
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
79
|
+
export const TreeMode: Story = {
|
|
80
|
+
render: () => <TreeModeDemo />,
|
|
81
|
+
};
|
|
96
82
|
|
|
97
|
-
|
|
83
|
+
// 无菜单栏的只读树形模式
|
|
84
|
+
const NoMenuBarDemo = () => {
|
|
98
85
|
const [value, setValue] = useState(
|
|
99
86
|
JSON.stringify(
|
|
100
87
|
{
|
|
101
88
|
name: 'world',
|
|
102
89
|
},
|
|
103
90
|
null,
|
|
104
|
-
2
|
|
105
|
-
)
|
|
91
|
+
2,
|
|
92
|
+
),
|
|
106
93
|
);
|
|
107
94
|
|
|
108
95
|
return (
|
|
@@ -110,20 +97,8 @@ function Demo() {
|
|
|
110
97
|
<EditorJSON value={value} onChange={setValue} readonly mode="tree" mainMenuBar={false} />
|
|
111
98
|
</div>
|
|
112
99
|
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export default Demo;
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## API
|
|
119
|
-
|
|
120
|
-
```tsx | pure
|
|
121
|
-
import type { JSONEditor } from 'vanilla-jsoneditor';
|
|
100
|
+
};
|
|
122
101
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
readonly?: boolean;
|
|
127
|
-
mode?: JSONEditor['mode'];
|
|
128
|
-
}
|
|
129
|
-
```
|
|
102
|
+
export const NoMenuBar: Story = {
|
|
103
|
+
render: () => <NoMenuBarDemo />,
|
|
104
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { EditorLogs } from '@fe-free/core';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof EditorLogs> = {
|
|
5
|
+
title: '@fe-free/core/EditorLogs',
|
|
6
|
+
component: EditorLogs,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'一个用于显示日志内容的 React 组件。它使用 CodeMirror 编辑器来呈现日志,提供了语法高亮和主题支持。',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
type Story = StoryObj<typeof EditorLogs>;
|
|
20
|
+
|
|
21
|
+
export const Basic: Story = {
|
|
22
|
+
args: {
|
|
23
|
+
logs: [
|
|
24
|
+
{
|
|
25
|
+
timestamp: '2023-01-01 12:00:00',
|
|
26
|
+
level: 'info',
|
|
27
|
+
message: 'This is an info log message.',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
timestamp: '2023-01-01 12:00:00',
|
|
31
|
+
level: 'warn',
|
|
32
|
+
message: 'This is a warning log message.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
timestamp: '2023-01-01 12:00:00',
|
|
36
|
+
level: 'error',
|
|
37
|
+
message: 'This is an error log message.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
timestamp: '2023-01-01 12:00:00',
|
|
41
|
+
level: 'system',
|
|
42
|
+
message:
|
|
43
|
+
'This is a debug log message. This is a debug log message This is a debug log message This is a debug log message This is a debug log message',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import CodeMirror from '@uiw/react-codemirror';
|
|
3
1
|
import { StreamLanguage } from '@codemirror/language';
|
|
4
|
-
import { createTheme } from '@uiw/codemirror-themes';
|
|
5
2
|
import { tags as t } from '@lezer/highlight';
|
|
3
|
+
import { createTheme } from '@uiw/codemirror-themes';
|
|
4
|
+
import CodeMirror from '@uiw/react-codemirror';
|
|
5
|
+
import React from 'react';
|
|
6
6
|
|
|
7
7
|
interface EditorLogsProps {
|
|
8
8
|
logs: {
|
|
@@ -67,3 +67,4 @@ const EditorLogs: React.FC<EditorLogsProps> = ({ logs }) => {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
export { EditorLogs };
|
|
70
|
+
export type { EditorLogsProps };
|