@fe-free/core 1.0.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.
@@ -0,0 +1,36 @@
1
+ import AceEditor from 'react-ace';
2
+
3
+ import 'ace-builds/src-noconflict/mode-javascript';
4
+ import 'ace-builds/src-noconflict/theme-monokai';
5
+ import 'ace-builds/src-noconflict/ext-language_tools';
6
+
7
+ const fullStyle = { width: '100%', height: '100%' };
8
+
9
+ interface EditorJavascriptProps {
10
+ value: string;
11
+ onChange?: (value: string, event?: any) => void;
12
+ readonly?: boolean;
13
+ }
14
+ function EditorJavascript({ value, onChange, readonly }: EditorJavascriptProps) {
15
+ return (
16
+ <AceEditor
17
+ style={fullStyle}
18
+ mode="javascript"
19
+ theme="monokai"
20
+ value={value}
21
+ onChange={onChange}
22
+ readOnly={readonly}
23
+ name="javascript_editor"
24
+ editorProps={{ $blockScrolling: true }}
25
+ setOptions={{
26
+ enableBasicAutocompletion: true,
27
+ enableLiveAutocompletion: true,
28
+ enableSnippets: true,
29
+ showLineNumbers: true,
30
+ tabSize: 2,
31
+ }}
32
+ />
33
+ );
34
+ }
35
+
36
+ export { EditorJavascript };
@@ -0,0 +1,129 @@
1
+ ---
2
+ group: 'core'
3
+ toc: content
4
+ ---
5
+
6
+ # EditorJSON
7
+
8
+ ## 代码演示
9
+
10
+ ### 常规
11
+
12
+ ```tsx
13
+ import { useState } from 'react';
14
+ import { EditorJSON } from '@fe-free/core';
15
+
16
+ function Demo() {
17
+ const [value, setValue] = useState(
18
+ JSON.stringify(
19
+ {
20
+ name: 'world',
21
+ },
22
+ null,
23
+ 2
24
+ )
25
+ );
26
+
27
+ return (
28
+ <div style={{ width: '500px', height: '500px' }}>
29
+ <EditorJSON value={value} onChange={setValue} />
30
+ </div>
31
+ );
32
+ }
33
+
34
+ export default Demo;
35
+ ```
36
+
37
+ ### 只读
38
+
39
+ ```tsx
40
+ import { useState } from 'react';
41
+ import { EditorJSON } from '@fe-free/core';
42
+
43
+ function Demo() {
44
+ const [value, setValue] = useState(
45
+ JSON.stringify(
46
+ {
47
+ name: 'world',
48
+ },
49
+ null,
50
+ 2
51
+ )
52
+ );
53
+
54
+ return (
55
+ <div style={{ width: '500px', height: '500px' }}>
56
+ <EditorJSON value={value} onChange={setValue} readonly />
57
+ </div>
58
+ );
59
+ }
60
+
61
+ export default Demo;
62
+ ```
63
+
64
+ ### mode
65
+
66
+ ```tsx
67
+ import { useState } from 'react';
68
+ import { EditorJSON } from '@fe-free/core';
69
+
70
+ function Demo() {
71
+ const [value, setValue] = useState(
72
+ JSON.stringify(
73
+ {
74
+ name: 'world',
75
+ },
76
+ null,
77
+ 2
78
+ )
79
+ );
80
+
81
+ return (
82
+ <div style={{ width: '500px', height: '500px' }}>
83
+ <EditorJSON value={value} onChange={setValue} mode="tree" readonly />
84
+ </div>
85
+ );
86
+ }
87
+
88
+ export default Demo;
89
+ ```
90
+
91
+ ### readonly mainMenuBar mode
92
+
93
+ ```tsx
94
+ import { useState } from 'react';
95
+ import { EditorJSON } from '@fe-free/core';
96
+
97
+ function Demo() {
98
+ const [value, setValue] = useState(
99
+ JSON.stringify(
100
+ {
101
+ name: 'world',
102
+ },
103
+ null,
104
+ 2
105
+ )
106
+ );
107
+
108
+ return (
109
+ <div style={{ width: '500px', height: '500px' }}>
110
+ <EditorJSON value={value} onChange={setValue} readonly mode="tree" mainMenuBar={false} />
111
+ </div>
112
+ );
113
+ }
114
+
115
+ export default Demo;
116
+ ```
117
+
118
+ ## API
119
+
120
+ ```tsx | pure
121
+ import type { JSONEditor } from 'vanilla-jsoneditor';
122
+
123
+ interface EditorJSONProps {
124
+ value: string;
125
+ onChange: (value: string, event?: any) => void;
126
+ readonly?: boolean;
127
+ mode?: JSONEditor['mode'];
128
+ }
129
+ ```
@@ -0,0 +1,48 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import type { Mode } from 'vanilla-jsoneditor';
3
+ import { JSONEditor } from 'vanilla-jsoneditor';
4
+
5
+ interface EditorJSONProps {
6
+ value: string;
7
+ onChange?: (value: string, event?: any) => void;
8
+ readonly?: boolean;
9
+ mode?: 'text' | 'tree' | 'table';
10
+ mainMenuBar?: boolean;
11
+ }
12
+
13
+ function EditorJSON({ value, onChange, readonly, mode, mainMenuBar }: EditorJSONProps) {
14
+ const ref = useRef<HTMLDivElement>(null);
15
+ const refEditor = useRef<JSONEditor | null>(null);
16
+
17
+ const refOnChange = useRef(onChange);
18
+
19
+ useEffect(() => {
20
+ refEditor.current?.update({
21
+ text: value || '',
22
+ });
23
+ }, [value]);
24
+
25
+ useEffect(() => {
26
+ refEditor.current = new JSONEditor({
27
+ target: ref.current!,
28
+ props: {
29
+ mainMenuBar,
30
+ tabSize: 2,
31
+ mode: (mode || 'text') as Mode,
32
+ readOnly: readonly,
33
+ askToFormat: false,
34
+ content: {
35
+ text: value || '',
36
+ },
37
+ onChange: (newContent) => {
38
+ // @ts-ignore
39
+ refOnChange.current(newContent.text);
40
+ },
41
+ },
42
+ });
43
+ }, []);
44
+
45
+ return <div ref={ref} className="h-full w-full" />;
46
+ }
47
+
48
+ export { EditorJSON };
@@ -0,0 +1,48 @@
1
+ ---
2
+ group: 'core'
3
+ toc: content
4
+ ---
5
+
6
+ # EditorLogs
7
+
8
+ `LogViewer` 是一个用于显示日志内容的 React 组件。它使用 CodeMirror 编辑器来呈现日志,提供了语法高亮和主题支持。
9
+
10
+ ## 代码演示
11
+
12
+ ### 常规
13
+
14
+ ```tsx
15
+ import { EditorLogs } from '@fe-free/core';
16
+
17
+ function Demo() {
18
+ return (
19
+ <EditorLogs
20
+ logs={[
21
+ {
22
+ timestamp: '2023-01-01 12:00:00',
23
+ level: 'info',
24
+ message: 'This is an info log message.',
25
+ },
26
+ {
27
+ timestamp: '2023-01-01 12:00:00',
28
+ level: 'warn',
29
+ message: 'This is a warning log message.',
30
+ },
31
+ {
32
+ timestamp: '2023-01-01 12:00:00',
33
+ level: 'error',
34
+ message: 'This is an error log message.',
35
+ },
36
+ {
37
+ timestamp: '2023-01-01 12:00:00',
38
+ level: 'system',
39
+ message:
40
+ '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',
41
+ },
42
+ ]}
43
+ />
44
+ );
45
+ }
46
+
47
+ export default Demo;
48
+ ```
@@ -0,0 +1,69 @@
1
+ import React from 'react';
2
+ import CodeMirror from '@uiw/react-codemirror';
3
+ import { StreamLanguage } from '@codemirror/language';
4
+ import { createTheme } from '@uiw/codemirror-themes';
5
+ import { tags as t } from '@lezer/highlight';
6
+
7
+ interface EditorLogsProps {
8
+ logs: {
9
+ timestamp: string;
10
+ level: 'info' | 'warn' | 'error' | 'system';
11
+ message: string;
12
+ }[];
13
+ }
14
+
15
+ const EditorLogs: React.FC<EditorLogsProps> = ({ logs }) => {
16
+ const formattedLogs = logs
17
+ .map((log) => {
18
+ const levelPadded = `[${log.level}]`.padEnd(8, ' ');
19
+ return `${log.timestamp} ${levelPadded.toUpperCase()} ${log.message}`;
20
+ })
21
+ .join('\n');
22
+
23
+ const logExtension = [
24
+ StreamLanguage.define({
25
+ token: (stream) => {
26
+ if (stream.match(/.*\[WARN\s*\].*/)) return 'keyword';
27
+ if (stream.match(/.*\[ERROR\s*\].*/)) return 'invalid';
28
+ if (stream.match(/.*\[SYSTEM\].*/)) return 'comment';
29
+ stream.next();
30
+ return null;
31
+ },
32
+ }),
33
+ ];
34
+
35
+ const myTheme = createTheme({
36
+ theme: 'dark',
37
+ settings: {
38
+ background: '#2e3235',
39
+ foreground: 'rgba(243, 244, 246, 1)',
40
+ },
41
+ styles: [
42
+ {
43
+ tag: t.keyword,
44
+ color: 'rgba(252, 211, 77, 1)',
45
+ },
46
+ {
47
+ tag: t.invalid,
48
+ color: 'rgba(248, 113, 113, 1)',
49
+ },
50
+ {
51
+ tag: t.comment,
52
+ color: 'rgba(96, 165, 250, 1)',
53
+ },
54
+ ],
55
+ });
56
+
57
+ return (
58
+ <CodeMirror
59
+ value={formattedLogs}
60
+ theme={myTheme}
61
+ extensions={logExtension}
62
+ editable={false}
63
+ height="400px"
64
+ style={{ overflowY: 'auto' }}
65
+ />
66
+ );
67
+ };
68
+
69
+ export { EditorLogs };
@@ -0,0 +1,40 @@
1
+ ---
2
+ group: 'core'
3
+ toc: content
4
+ ---
5
+
6
+ # EditorMarkdown
7
+
8
+ ## 代码演示
9
+
10
+ ### 常规
11
+
12
+ ```tsx
13
+ import { useState } from 'react';
14
+ import { EditorMarkdown } from '@fe-free/core';
15
+
16
+ function Demo() {
17
+ const [value] = useState(
18
+ `# hello
19
+
20
+ world
21
+ `
22
+ );
23
+
24
+ return (
25
+ <div style={{ width: '500px', height: '500px' }}>
26
+ <EditorMarkdown value={value} />
27
+ </div>
28
+ );
29
+ }
30
+
31
+ export default Demo;
32
+ ```
33
+
34
+ ## API
35
+
36
+ ```tsx | pure
37
+ interface EditorMarkdownProps {
38
+ value: string;
39
+ }
40
+ ```
@@ -0,0 +1,39 @@
1
+ import Markdown from 'react-markdown';
2
+ import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
3
+
4
+ interface EditorMarkdownProps {
5
+ value: string;
6
+ }
7
+
8
+ function EditorMarkdown({ value }: EditorMarkdownProps) {
9
+ return (
10
+ <Markdown
11
+ unwrapDisallowed
12
+ components={{
13
+ code(props) {
14
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
+ const { children, className, node, ...rest } = props;
16
+ const match = /language-(\w+)/.exec(className || '');
17
+ return match ? (
18
+ <SyntaxHighlighter
19
+ {...rest}
20
+ PreTag="div"
21
+ wrapLongLines
22
+ // eslint-disable-next-line react/no-children-prop
23
+ children={String(children).replace(/\n$/, '')}
24
+ language={match[1].toLowerCase()}
25
+ />
26
+ ) : (
27
+ <code {...rest} className={className}>
28
+ {children}
29
+ </code>
30
+ );
31
+ },
32
+ }}
33
+ >
34
+ {value || ''}
35
+ </Markdown>
36
+ );
37
+ }
38
+
39
+ export { EditorMarkdown };
@@ -0,0 +1,96 @@
1
+ ---
2
+ group: 'core'
3
+ toc: content
4
+ ---
5
+
6
+ # Form
7
+
8
+ ## ProFormJSON
9
+
10
+ JSON
11
+
12
+ ```tsx
13
+ import { ProForm } from '@ant-design/pro-components';
14
+ import { ProFormJSON } from '@fe-free/core';
15
+
16
+ function Demo() {
17
+ return (
18
+ <ProForm>
19
+ <ProFormJSON name="json" initialValue={JSON.stringify({ name: 'world' }, null, 2)} />
20
+ </ProForm>
21
+ );
22
+ }
23
+
24
+ export default Demo;
25
+ ```
26
+
27
+ readonly
28
+
29
+ ```tsx
30
+ import { ProForm } from '@ant-design/pro-components';
31
+ import { ProFormJSON } from '@fe-free/core';
32
+
33
+ function Demo() {
34
+ return (
35
+ <ProForm>
36
+ <ProFormJSON
37
+ name="json"
38
+ readonly
39
+ initialValue={JSON.stringify({ name: 'world' }, null, 2)}
40
+ fieldProps={{
41
+ mainMenuBar: false,
42
+ }}
43
+ />
44
+ </ProForm>
45
+ );
46
+ }
47
+
48
+ export default Demo;
49
+ ```
50
+
51
+ ## ProFormJavascript
52
+
53
+ JSON
54
+
55
+ ```tsx
56
+ import { ProForm } from '@ant-design/pro-components';
57
+ import { ProFormJavascript } from '@fe-free/core';
58
+
59
+ function Demo() {
60
+ return (
61
+ <ProForm>
62
+ <ProFormJavascript
63
+ name="json"
64
+ initialValue={`const name = 'world';
65
+ console.log('hello', name);
66
+ `}
67
+ />
68
+ </ProForm>
69
+ );
70
+ }
71
+
72
+ export default Demo;
73
+ ```
74
+
75
+ readonly
76
+
77
+ ```tsx
78
+ import { ProForm } from '@ant-design/pro-components';
79
+ import { ProFormJavascript } from '@fe-free/core';
80
+
81
+ function Demo() {
82
+ return (
83
+ <ProForm>
84
+ <ProFormJavascript
85
+ name="json"
86
+ readonly
87
+ initialValue={`const name = 'world';
88
+ console.log('hello', name);
89
+ `}
90
+ />
91
+ </ProForm>
92
+ );
93
+ }
94
+
95
+ export default Demo;
96
+ ```
@@ -0,0 +1,51 @@
1
+ import type { ProFormItemProps } from '@ant-design/pro-components';
2
+ import { ProForm } from '@ant-design/pro-components';
3
+ import { EditorJSON } from '../editor_json';
4
+ import { EditorJavascript } from '../editor_javascript';
5
+ import { pinyinMatch } from '@fe-free/tool';
6
+
7
+ function JSONItem(props) {
8
+ return (
9
+ <div style={{ height: '300px' }}>
10
+ <EditorJSON {...props} />
11
+ </div>
12
+ );
13
+ }
14
+
15
+ function ProFormJSON(props: ProFormItemProps) {
16
+ const { readonly, fieldProps, ...rest } = props;
17
+ return (
18
+ <ProForm.Item {...rest}>
19
+ <JSONItem readonly={readonly} {...fieldProps} />
20
+ </ProForm.Item>
21
+ );
22
+ }
23
+
24
+ function JavascriptItem(props) {
25
+ return (
26
+ <div style={{ height: '300px' }}>
27
+ <EditorJavascript {...props} />
28
+ </div>
29
+ );
30
+ }
31
+
32
+ function ProFormJavascript(props: ProFormItemProps) {
33
+ const { readonly, fieldProps, ...rest } = props;
34
+ return (
35
+ <ProForm.Item {...rest}>
36
+ <JavascriptItem readonly={readonly} {...fieldProps} />
37
+ </ProForm.Item>
38
+ );
39
+ }
40
+
41
+ /** ProFromSelect 搜索相关 props。 支持 1 搜索 2 拼音过滤 */
42
+ const proFormSelectSearchProps = {
43
+ fieldProps: {
44
+ showSearch: true,
45
+ filterOption: (input, option) => pinyinMatch(option.label, input),
46
+ // 本地过滤,关闭搜索 fetch data
47
+ fetchDataOnSearch: false,
48
+ },
49
+ };
50
+
51
+ export { ProFormJSON, ProFormJavascript, proFormSelectSearchProps };
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ export { CRUD } from './crud';
2
+ export type { CRUDProps, CRUDMethods } from './crud';
3
+
4
+ export { ProFormJSON, ProFormJavascript, proFormSelectSearchProps } from './form';
5
+
6
+ export { LoadingButton } from './button';
7
+
8
+ export { Table } from './table';
9
+ export type { TableProps } from './table';
10
+
11
+ export { EditorJavascript } from './editor_javascript';
12
+ export { EditorJSON } from './editor_json';
13
+ export { EditorMarkdown } from './editor_markdown';
14
+ export { EditorLogs } from './editor_logs';
15
+
16
+ export { customValueTypeMap, CustomValueTypeEnum } from './value_type_map';
@@ -0,0 +1,89 @@
1
+ ---
2
+ group: 'core'
3
+ toc: content
4
+ ---
5
+
6
+ # Table
7
+
8
+ 对 ProTable 做扩展以满足实际使用情况
9
+
10
+ - 默认搜索关闭,需要再打开 `search: true`
11
+ - 有搜索的时候才显示搜索区域
12
+
13
+ ## 场景
14
+
15
+ ### 常规
16
+
17
+ ```tsx
18
+ import { Table } from '@fe-free/core';
19
+ import { fakeData } from '../crud/demo/data';
20
+
21
+ function fakeRequest() {
22
+ return Promise.resolve({
23
+ data: fakeData,
24
+ success: true,
25
+ total: fakeData.length,
26
+ });
27
+ }
28
+
29
+ const Demo = () => {
30
+ const columns = [
31
+ {
32
+ title: 'id',
33
+ dataIndex: 'id',
34
+ search: true,
35
+ },
36
+ {
37
+ title: '名字(省略)',
38
+ dataIndex: 'name',
39
+ search: true,
40
+ ellipsis: true,
41
+ },
42
+ {
43
+ title: 'city',
44
+ dataIndex: 'city',
45
+ },
46
+ {
47
+ title: 'area',
48
+ dataIndex: 'area',
49
+ },
50
+ ];
51
+
52
+ return <Table rowKey="id" columns={columns} request={fakeRequest} />;
53
+ };
54
+
55
+ export default Demo;
56
+ ```
57
+
58
+ ### 没有搜索
59
+
60
+ ```tsx
61
+ import { Table } from '@fe-free/core';
62
+
63
+ const Demo = () => {
64
+ const columns = [
65
+ {
66
+ title: 'id',
67
+ dataIndex: 'id',
68
+ },
69
+ {
70
+ title: '名字(省略)',
71
+ dataIndex: 'name',
72
+
73
+ ellipsis: true,
74
+ },
75
+ {
76
+ title: 'city',
77
+ dataIndex: 'city',
78
+ },
79
+ {
80
+ title: 'area',
81
+ dataIndex: 'area',
82
+ },
83
+ ];
84
+
85
+ return <Table columns={columns} rowKey="id" />;
86
+ };
87
+
88
+ export default Demo;
89
+ ```