listpage-next 0.0.53 → 0.0.54
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/dist/components/DataTable/components/DataTable.js +7 -2
- package/dist/components/Page/components/ListPage/index.d.ts +5 -1
- package/dist/components/Page/components/ListPage/index.js +8 -3
- package/dist/context/index.d.ts +1 -0
- package/dist/context/index.js +2 -0
- package/dist/demos/demo7.d.ts +1 -0
- package/dist/demos/demo7.js +12 -0
- package/dist/features/JsonEditor/Container.d.ts +12 -0
- package/dist/features/JsonEditor/Container.js +122 -0
- package/dist/features/JsonEditor/LineNumberEditor.d.ts +10 -0
- package/dist/features/JsonEditor/LineNumberEditor.js +185 -0
- package/dist/features/JsonEditor/index.d.ts +1 -0
- package/dist/features/JsonEditor/index.js +2 -0
- package/dist/features/JsonEditor/style.d.ts +13 -0
- package/dist/features/JsonEditor/style.js +184 -0
- package/dist/features/JsonEditor/utils.d.ts +2 -0
- package/dist/features/JsonEditor/utils.js +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
- /package/dist/{components/DataTable/context/index.d.ts → context/float.d.ts} +0 -0
- /package/dist/{components/DataTable/context/index.js → context/float.js} +0 -0
|
@@ -3,7 +3,7 @@ import styled_components from "styled-components";
|
|
|
3
3
|
import { Card, Pagination, Table } from "antd";
|
|
4
4
|
import { useColumns } from "../hooks/useColumns.js";
|
|
5
5
|
import { useData } from "../hooks/useData.js";
|
|
6
|
-
import { FloatProvider, useFloatContext } from "
|
|
6
|
+
import { FloatProvider, useFloatContext } from "../../../context/index.js";
|
|
7
7
|
const PaginationContainer = styled_components.div`
|
|
8
8
|
padding: 12px 16px 12px 0;
|
|
9
9
|
border-top: 1px solid #f0f0f0;
|
|
@@ -63,10 +63,15 @@ const DataTableComponent = (props)=>{
|
|
|
63
63
|
]
|
|
64
64
|
});
|
|
65
65
|
};
|
|
66
|
-
const DataTable = (props)
|
|
66
|
+
const DataTable = (props)=>{
|
|
67
|
+
if (!props.floats) return /*#__PURE__*/ jsx(DataTableComponent, {
|
|
68
|
+
...props
|
|
69
|
+
});
|
|
70
|
+
return /*#__PURE__*/ jsx(FloatProvider, {
|
|
67
71
|
floats: props.floats,
|
|
68
72
|
children: /*#__PURE__*/ jsx(DataTableComponent, {
|
|
69
73
|
...props
|
|
70
74
|
})
|
|
71
75
|
});
|
|
76
|
+
};
|
|
72
77
|
export { DataTable, DataTableComponent };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JSX } from 'react';
|
|
1
2
|
import { FilterFormProps } from '../../../FilterGroup/components/FilterForm';
|
|
2
3
|
export interface ListPageProps {
|
|
3
4
|
title?: React.ReactNode;
|
|
@@ -6,7 +7,10 @@ export interface ListPageProps {
|
|
|
6
7
|
filterProps?: FilterFormProps;
|
|
7
8
|
toolbar?: React.ReactNode;
|
|
8
9
|
body?: React.ReactNode;
|
|
9
|
-
floats?:
|
|
10
|
+
floats?: {
|
|
11
|
+
key: string;
|
|
12
|
+
content: JSX.Element;
|
|
13
|
+
}[];
|
|
10
14
|
style?: React.CSSProperties;
|
|
11
15
|
}
|
|
12
16
|
export declare const ListPage: (props: ListPageProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,6 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
import { Card } from "antd";
|
|
4
4
|
import { FilterForm } from "../../../FilterGroup/components/FilterForm/index.js";
|
|
5
|
+
import { FloatProvider } from "../../../../context/index.js";
|
|
5
6
|
import { BodySection, FilterSection, HeaderSection, ListPageContainer, Title, ToolbarSection } from "./styles.js";
|
|
6
7
|
const ListPage = (props)=>{
|
|
7
8
|
const { title, extra, filterProps, toolbar, body, style, floats } = props;
|
|
@@ -17,7 +18,7 @@ const ListPage = (props)=>{
|
|
|
17
18
|
props.filter,
|
|
18
19
|
filterProps
|
|
19
20
|
]);
|
|
20
|
-
|
|
21
|
+
const page = /*#__PURE__*/ jsxs(ListPageContainer, {
|
|
21
22
|
style: style,
|
|
22
23
|
children: [
|
|
23
24
|
/*#__PURE__*/ jsxs(HeaderSection, {
|
|
@@ -38,9 +39,13 @@ const ListPage = (props)=>{
|
|
|
38
39
|
}),
|
|
39
40
|
/*#__PURE__*/ jsx(BodySection, {
|
|
40
41
|
children: body
|
|
41
|
-
})
|
|
42
|
-
floats
|
|
42
|
+
})
|
|
43
43
|
]
|
|
44
44
|
});
|
|
45
|
+
if (!floats) return page;
|
|
46
|
+
return /*#__PURE__*/ jsx(FloatProvider, {
|
|
47
|
+
floats: floats,
|
|
48
|
+
children: page
|
|
49
|
+
});
|
|
45
50
|
};
|
|
46
51
|
export { ListPage };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FloatContext, FloatProvider, useFloatContext } from './float';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const Demo7: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { JsonEditor } from "../features/JsonEditor/index.js";
|
|
4
|
+
const Demo7 = ()=>{
|
|
5
|
+
const [value, onChange] = useState();
|
|
6
|
+
return /*#__PURE__*/ jsx(JsonEditor, {
|
|
7
|
+
height: 100,
|
|
8
|
+
value: value,
|
|
9
|
+
onChange: onChange
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
export { Demo7 };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface JsonEditorProps {
|
|
3
|
+
value?: any;
|
|
4
|
+
onChange?: (value: any) => void;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
readOnly?: boolean;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
className?: string;
|
|
9
|
+
height?: number | string;
|
|
10
|
+
}
|
|
11
|
+
export declare const JsonEditor: React.FC<JsonEditorProps>;
|
|
12
|
+
export default JsonEditor;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { Button } from "antd";
|
|
4
|
+
import { CompressOutlined, FormatPainterOutlined } from "@ant-design/icons";
|
|
5
|
+
import { LineNumberEditor } from "./LineNumberEditor.js";
|
|
6
|
+
import { CardHeader, EditorWrapper, ErrorMessage, HeaderActions, HeaderTitle, JsonEditorContainer } from "./style.js";
|
|
7
|
+
const JsonEditor = ({ value, onChange, placeholder = 'Enter JSON here...', readOnly = false, style, className, height })=>{
|
|
8
|
+
const [textValue, setTextValue] = useState('');
|
|
9
|
+
const [error, setError] = useState(null);
|
|
10
|
+
useEffect(()=>{
|
|
11
|
+
if (void 0 !== value) if ('string' == typeof value) {
|
|
12
|
+
setTextValue(value);
|
|
13
|
+
setError(null);
|
|
14
|
+
} else try {
|
|
15
|
+
const jsonString = JSON.stringify(value, null, 2);
|
|
16
|
+
setTextValue(jsonString);
|
|
17
|
+
setError(null);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
setTextValue('');
|
|
20
|
+
setError('Invalid JSON value provided');
|
|
21
|
+
}
|
|
22
|
+
else setTextValue('');
|
|
23
|
+
}, [
|
|
24
|
+
value
|
|
25
|
+
]);
|
|
26
|
+
const handleChange = (newText)=>{
|
|
27
|
+
setTextValue(newText);
|
|
28
|
+
if (readOnly) return;
|
|
29
|
+
if ('' === newText.trim() || !newText.startsWith('{') && !newText.startsWith('[')) {
|
|
30
|
+
onChange?.(newText);
|
|
31
|
+
setError(null);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
if ('' === newText.trim()) {
|
|
36
|
+
onChange?.(void 0);
|
|
37
|
+
setError(null);
|
|
38
|
+
} else {
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(newText);
|
|
42
|
+
} catch (parseError) {
|
|
43
|
+
parsed = newText;
|
|
44
|
+
}
|
|
45
|
+
onChange?.(parsed);
|
|
46
|
+
setError(null);
|
|
47
|
+
}
|
|
48
|
+
} catch (err) {
|
|
49
|
+
setError('Invalid JSON format');
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const handleFormat = ()=>{
|
|
53
|
+
if ('' === textValue.trim() || !textValue.startsWith('{') && !textValue.startsWith('[')) return void setError(null);
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(textValue);
|
|
56
|
+
const formatted = JSON.stringify(parsed, null, 2);
|
|
57
|
+
setTextValue(formatted);
|
|
58
|
+
setError(null);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
setError('Cannot format: Invalid JSON');
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const handleCompress = ()=>{
|
|
64
|
+
if ('' === textValue.trim() || !textValue.startsWith('{') && !textValue.startsWith('[')) return void setError(null);
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(textValue);
|
|
67
|
+
const compressed = JSON.stringify(parsed);
|
|
68
|
+
setTextValue(compressed);
|
|
69
|
+
setError(null);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
setError('Cannot compress: Invalid JSON');
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return /*#__PURE__*/ jsxs(JsonEditorContainer, {
|
|
75
|
+
className: className,
|
|
76
|
+
style: {
|
|
77
|
+
...style,
|
|
78
|
+
height: height || style?.height
|
|
79
|
+
},
|
|
80
|
+
children: [
|
|
81
|
+
/*#__PURE__*/ jsxs(CardHeader, {
|
|
82
|
+
children: [
|
|
83
|
+
/*#__PURE__*/ jsx(HeaderTitle, {
|
|
84
|
+
children: "JSON"
|
|
85
|
+
}),
|
|
86
|
+
/*#__PURE__*/ jsxs(HeaderActions, {
|
|
87
|
+
children: [
|
|
88
|
+
/*#__PURE__*/ jsx(Button, {
|
|
89
|
+
onClick: handleFormat,
|
|
90
|
+
disabled: readOnly,
|
|
91
|
+
size: "small",
|
|
92
|
+
icon: /*#__PURE__*/ jsx(FormatPainterOutlined, {}),
|
|
93
|
+
title: "Format JSON"
|
|
94
|
+
}),
|
|
95
|
+
/*#__PURE__*/ jsx(Button, {
|
|
96
|
+
onClick: handleCompress,
|
|
97
|
+
disabled: readOnly,
|
|
98
|
+
size: "small",
|
|
99
|
+
icon: /*#__PURE__*/ jsx(CompressOutlined, {}),
|
|
100
|
+
title: "Compress JSON"
|
|
101
|
+
})
|
|
102
|
+
]
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
}),
|
|
106
|
+
/*#__PURE__*/ jsx(EditorWrapper, {
|
|
107
|
+
children: /*#__PURE__*/ jsx(LineNumberEditor, {
|
|
108
|
+
value: textValue,
|
|
109
|
+
onChange: handleChange,
|
|
110
|
+
placeholder: placeholder,
|
|
111
|
+
readOnly: readOnly,
|
|
112
|
+
hasError: !!error
|
|
113
|
+
})
|
|
114
|
+
}),
|
|
115
|
+
error && /*#__PURE__*/ jsx(ErrorMessage, {
|
|
116
|
+
children: error
|
|
117
|
+
})
|
|
118
|
+
]
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
const Container = JsonEditor;
|
|
122
|
+
export { JsonEditor, Container as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface LineNumberEditorProps {
|
|
3
|
+
value: string;
|
|
4
|
+
onChange: (value: string) => void;
|
|
5
|
+
readOnly?: boolean;
|
|
6
|
+
hasError?: boolean;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const LineNumberEditor: React.FC<LineNumberEditorProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import styled_components from "styled-components";
|
|
4
|
+
import { calculateLineCount, highlightJson } from "./utils.js";
|
|
5
|
+
const EditorContainer = styled_components.div`
|
|
6
|
+
display: flex;
|
|
7
|
+
height: 100%;
|
|
8
|
+
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
|
9
|
+
font-size: 12px;
|
|
10
|
+
line-height: 1.5;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
`;
|
|
14
|
+
const LineNumbers = styled_components.div`
|
|
15
|
+
padding: 4px 8px;
|
|
16
|
+
text-align: right;
|
|
17
|
+
background-color: #f0f0f0;
|
|
18
|
+
color: #999;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
user-select: none;
|
|
21
|
+
flex-shrink: 0;
|
|
22
|
+
border-right: 1px solid #ddd;
|
|
23
|
+
font-family: inherit;
|
|
24
|
+
font-size: inherit;
|
|
25
|
+
line-height: inherit;
|
|
26
|
+
box-sizing: border-box;
|
|
27
|
+
`;
|
|
28
|
+
const TextAreaContainer = styled_components.div`
|
|
29
|
+
flex: 1;
|
|
30
|
+
position: relative;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
`;
|
|
34
|
+
const StyledTextArea = styled_components.textarea`
|
|
35
|
+
position: absolute;
|
|
36
|
+
top: 0;
|
|
37
|
+
left: 0;
|
|
38
|
+
width: 100%;
|
|
39
|
+
height: 100%;
|
|
40
|
+
padding: 4px 8px;
|
|
41
|
+
border: none;
|
|
42
|
+
resize: none;
|
|
43
|
+
font-family: inherit;
|
|
44
|
+
font-size: inherit;
|
|
45
|
+
line-height: inherit;
|
|
46
|
+
background-color: transparent;
|
|
47
|
+
outline: none;
|
|
48
|
+
overflow: auto;
|
|
49
|
+
white-space: pre;
|
|
50
|
+
tab-size: 2;
|
|
51
|
+
box-sizing: border-box;
|
|
52
|
+
color: transparent; /* 文字透明 */
|
|
53
|
+
caret-color: #000; /* 但光标是黑色的 */
|
|
54
|
+
|
|
55
|
+
${(props)=>props.hasError && `
|
|
56
|
+
box-shadow: inset 0 0 0 1px #ff4d4f;
|
|
57
|
+
`}
|
|
58
|
+
|
|
59
|
+
&:focus {
|
|
60
|
+
box-shadow: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&::-webkit-scrollbar {
|
|
64
|
+
width: 8px;
|
|
65
|
+
height: 8px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&::-webkit-scrollbar-track {
|
|
69
|
+
background: #f1f1f1;
|
|
70
|
+
border-radius: 4px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&::-webkit-scrollbar-thumb {
|
|
74
|
+
background: #c1c1c1;
|
|
75
|
+
border-radius: 4px;
|
|
76
|
+
|
|
77
|
+
&:hover {
|
|
78
|
+
background: #a8a8a8;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
const HighlightPreview = styled_components.div`
|
|
83
|
+
position: absolute;
|
|
84
|
+
top: 0;
|
|
85
|
+
left: 0;
|
|
86
|
+
width: 100%;
|
|
87
|
+
height: 100%;
|
|
88
|
+
padding: 4px 8px;
|
|
89
|
+
border: none;
|
|
90
|
+
resize: none;
|
|
91
|
+
font-family: inherit;
|
|
92
|
+
font-size: inherit;
|
|
93
|
+
line-height: inherit;
|
|
94
|
+
background-color: #fafafa;
|
|
95
|
+
pointer-events: none;
|
|
96
|
+
overflow: auto;
|
|
97
|
+
white-space: pre;
|
|
98
|
+
tab-size: 2;
|
|
99
|
+
box-sizing: border-box;
|
|
100
|
+
|
|
101
|
+
.json-key {
|
|
102
|
+
color: #92278f; /* 紫色 */
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.json-string {
|
|
106
|
+
color: #3a9aed; /* 蓝色 */
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.json-number {
|
|
110
|
+
color: #25aae1; /* 青色 */
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.json-boolean {
|
|
114
|
+
color: #f98280; /* 红色 */
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.json-null {
|
|
118
|
+
color: #f18f01; /* 橙色 */
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.json-punctuation {
|
|
122
|
+
color: #333; /* 深灰色 */
|
|
123
|
+
}
|
|
124
|
+
`;
|
|
125
|
+
const LineNumberEditor = ({ value, onChange, readOnly = false, hasError = false, placeholder = '' })=>{
|
|
126
|
+
const lineNumbersRef = useRef(null);
|
|
127
|
+
const textAreaRef = useRef(null);
|
|
128
|
+
const previewRef = useRef(null);
|
|
129
|
+
useEffect(()=>{
|
|
130
|
+
if (lineNumbersRef.current) {
|
|
131
|
+
const lineNumbers = [];
|
|
132
|
+
const lineCount = calculateLineCount(value);
|
|
133
|
+
for(let i = 1; i <= Math.max(lineCount, 1); i++)lineNumbers.push(`<div style="min-height: 1.5em; line-height: 1.5; box-sizing: border-box;">${i}</div>`);
|
|
134
|
+
lineNumbersRef.current.innerHTML = lineNumbers.join('');
|
|
135
|
+
}
|
|
136
|
+
}, [
|
|
137
|
+
value
|
|
138
|
+
]);
|
|
139
|
+
useEffect(()=>{
|
|
140
|
+
if (previewRef.current) previewRef.current.innerHTML = highlightJson(value);
|
|
141
|
+
}, [
|
|
142
|
+
value
|
|
143
|
+
]);
|
|
144
|
+
const handleScroll = ()=>{
|
|
145
|
+
if (textAreaRef.current && lineNumbersRef.current && previewRef.current) {
|
|
146
|
+
const scrollTop = textAreaRef.current.scrollTop;
|
|
147
|
+
const scrollLeft = textAreaRef.current.scrollLeft;
|
|
148
|
+
lineNumbersRef.current.scrollTop = scrollTop;
|
|
149
|
+
previewRef.current.scrollTop = scrollTop;
|
|
150
|
+
previewRef.current.scrollLeft = scrollLeft;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const syncCursorPosition = ()=>{
|
|
154
|
+
if (textAreaRef.current && previewRef.current) {
|
|
155
|
+
previewRef.current.scrollTop = textAreaRef.current.scrollTop;
|
|
156
|
+
previewRef.current.scrollLeft = textAreaRef.current.scrollLeft;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
return /*#__PURE__*/ jsxs(EditorContainer, {
|
|
160
|
+
children: [
|
|
161
|
+
/*#__PURE__*/ jsx(LineNumbers, {
|
|
162
|
+
ref: lineNumbersRef
|
|
163
|
+
}),
|
|
164
|
+
/*#__PURE__*/ jsxs(TextAreaContainer, {
|
|
165
|
+
children: [
|
|
166
|
+
/*#__PURE__*/ jsx(HighlightPreview, {
|
|
167
|
+
ref: previewRef
|
|
168
|
+
}),
|
|
169
|
+
/*#__PURE__*/ jsx(StyledTextArea, {
|
|
170
|
+
ref: textAreaRef,
|
|
171
|
+
value: value,
|
|
172
|
+
onChange: (e)=>onChange(e.target.value),
|
|
173
|
+
readOnly: readOnly,
|
|
174
|
+
hasError: hasError,
|
|
175
|
+
placeholder: placeholder,
|
|
176
|
+
onScroll: handleScroll,
|
|
177
|
+
onMouseUp: syncCursorPosition,
|
|
178
|
+
onKeyUp: syncCursorPosition
|
|
179
|
+
})
|
|
180
|
+
]
|
|
181
|
+
})
|
|
182
|
+
]
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
export { LineNumberEditor };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { JsonEditor, type JsonEditorProps } from './Container';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const JsonEditorContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
2
|
+
export declare const CardHeader: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
3
|
+
export declare const HeaderTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
4
|
+
export declare const HeaderActions: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
5
|
+
export declare const EditorWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
6
|
+
export declare const ErrorMessage: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
7
|
+
export declare const EditorContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
8
|
+
export declare const LineNumbers: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
9
|
+
export declare const TextAreaContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
10
|
+
export declare const StyledTextArea: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, {
|
|
11
|
+
hasError: boolean;
|
|
12
|
+
}>> & string;
|
|
13
|
+
export declare const HighlightPreview: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { styled } from "styled-components";
|
|
2
|
+
const JsonEditorContainer = styled.div`
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
height: 100%;
|
|
6
|
+
border: 1px solid #d9d9d9;
|
|
7
|
+
border-radius: 8px;
|
|
8
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
9
|
+
background: #fff;
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
`;
|
|
12
|
+
const CardHeader = styled.div`
|
|
13
|
+
display: flex;
|
|
14
|
+
justify-content: space-between;
|
|
15
|
+
align-items: center;
|
|
16
|
+
padding: 8px 12px;
|
|
17
|
+
border-bottom: 1px solid #d9d9d9;
|
|
18
|
+
flex: 0 0 auto;
|
|
19
|
+
`;
|
|
20
|
+
const HeaderTitle = styled.div`
|
|
21
|
+
font-weight: 600;
|
|
22
|
+
color: #666;
|
|
23
|
+
font-size: 12px;
|
|
24
|
+
text-transform: uppercase;
|
|
25
|
+
letter-spacing: 0.5px;
|
|
26
|
+
`;
|
|
27
|
+
const HeaderActions = styled.div`
|
|
28
|
+
display: flex;
|
|
29
|
+
gap: 8px;
|
|
30
|
+
`;
|
|
31
|
+
const EditorWrapper = styled.div`
|
|
32
|
+
flex: 1;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
border-radius: 0 0 8px 8px;
|
|
35
|
+
background-color: #fafafa;
|
|
36
|
+
|
|
37
|
+
// 自定义滚动条样式
|
|
38
|
+
::-webkit-scrollbar {
|
|
39
|
+
width: 8px;
|
|
40
|
+
height: 8px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
::-webkit-scrollbar-track {
|
|
44
|
+
background: #f1f1f1;
|
|
45
|
+
border-radius: 4px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
::-webkit-scrollbar-thumb {
|
|
49
|
+
background: #c1c1c1;
|
|
50
|
+
border-radius: 4px;
|
|
51
|
+
|
|
52
|
+
&:hover {
|
|
53
|
+
background: #a8a8a8;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
::-webkit-scrollbar-corner {
|
|
58
|
+
background: transparent;
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
const ErrorMessage = styled.div`
|
|
62
|
+
color: #ff4d4f;
|
|
63
|
+
font-size: 12px;
|
|
64
|
+
margin-top: 4px;
|
|
65
|
+
min-height: 18px;
|
|
66
|
+
flex: 0 0 auto;
|
|
67
|
+
padding: 0 8px 8px;
|
|
68
|
+
`;
|
|
69
|
+
const EditorContainer = styled.div`
|
|
70
|
+
display: flex;
|
|
71
|
+
height: 100%;
|
|
72
|
+
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
|
73
|
+
font-size: 12px;
|
|
74
|
+
line-height: 1.5;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
box-sizing: border-box;
|
|
77
|
+
`;
|
|
78
|
+
const LineNumbers = styled.div`
|
|
79
|
+
padding: 4px 8px;
|
|
80
|
+
text-align: right;
|
|
81
|
+
background-color: #f0f0f0;
|
|
82
|
+
color: #999;
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
user-select: none;
|
|
85
|
+
flex-shrink: 0;
|
|
86
|
+
border-right: 1px solid #ddd;
|
|
87
|
+
font-family: inherit;
|
|
88
|
+
font-size: inherit;
|
|
89
|
+
line-height: inherit;
|
|
90
|
+
box-sizing: border-box;
|
|
91
|
+
`;
|
|
92
|
+
const TextAreaContainer = styled.div`
|
|
93
|
+
flex: 1;
|
|
94
|
+
position: relative;
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
box-sizing: border-box;
|
|
97
|
+
`;
|
|
98
|
+
const StyledTextArea = styled.textarea`
|
|
99
|
+
position: absolute;
|
|
100
|
+
top: 0;
|
|
101
|
+
left: 0;
|
|
102
|
+
width: 100%;
|
|
103
|
+
height: 100%;
|
|
104
|
+
padding: 4px 8px;
|
|
105
|
+
border: none;
|
|
106
|
+
resize: none;
|
|
107
|
+
font-family: inherit;
|
|
108
|
+
font-size: inherit;
|
|
109
|
+
line-height: inherit;
|
|
110
|
+
background-color: #fafafa;
|
|
111
|
+
outline: none;
|
|
112
|
+
overflow: auto;
|
|
113
|
+
white-space: pre;
|
|
114
|
+
tab-size: 2;
|
|
115
|
+
box-sizing: border-box;
|
|
116
|
+
|
|
117
|
+
${(props)=>props.hasError && `
|
|
118
|
+
box-shadow: inset 0 0 0 1px #ff4d4f;
|
|
119
|
+
`}
|
|
120
|
+
|
|
121
|
+
&:focus {
|
|
122
|
+
box-shadow: none;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
&::-webkit-scrollbar {
|
|
126
|
+
width: 8px;
|
|
127
|
+
height: 8px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
&::-webkit-scrollbar-track {
|
|
131
|
+
background: #f1f1f1;
|
|
132
|
+
border-radius: 4px;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&::-webkit-scrollbar-thumb {
|
|
136
|
+
background: #c1c1c1;
|
|
137
|
+
border-radius: 4px;
|
|
138
|
+
|
|
139
|
+
&:hover {
|
|
140
|
+
background: #a8a8a8;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
`;
|
|
144
|
+
const HighlightPreview = styled.div`
|
|
145
|
+
position: absolute;
|
|
146
|
+
top: 0;
|
|
147
|
+
left: 0;
|
|
148
|
+
width: 100%;
|
|
149
|
+
height: 100%;
|
|
150
|
+
padding: 4px 8px;
|
|
151
|
+
border: none;
|
|
152
|
+
resize: none;
|
|
153
|
+
font-family: inherit;
|
|
154
|
+
font-size: inherit;
|
|
155
|
+
line-height: inherit;
|
|
156
|
+
background-color: transparent;
|
|
157
|
+
pointer-events: none;
|
|
158
|
+
overflow: auto;
|
|
159
|
+
white-space: pre;
|
|
160
|
+
tab-size: 2;
|
|
161
|
+
color: transparent;
|
|
162
|
+
box-sizing: border-box;
|
|
163
|
+
|
|
164
|
+
.json-key {
|
|
165
|
+
color: #92278f;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.json-string {
|
|
169
|
+
color: #3a9aed;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.json-number {
|
|
173
|
+
color: #25aae1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.json-boolean {
|
|
177
|
+
color: #f98280;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.json-punctuation {
|
|
181
|
+
color: #333;
|
|
182
|
+
}
|
|
183
|
+
`;
|
|
184
|
+
export { CardHeader, EditorContainer, EditorWrapper, ErrorMessage, HeaderActions, HeaderTitle, HighlightPreview, JsonEditorContainer, LineNumbers, StyledTextArea, TextAreaContainer };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const highlightJson = (jsonString)=>{
|
|
2
|
+
const escapeHtml = (unsafe)=>unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3
|
+
if (!jsonString.trim().startsWith('{') && !jsonString.trim().startsWith('[')) return escapeHtml(jsonString);
|
|
4
|
+
try {
|
|
5
|
+
return escapeHtml(jsonString).replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:))/g, '<span class="json-key">$1</span>').replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(?!\s*:))/g, '<span class="json-string">$1</span>').replace(/(?<=:)\s*(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, ' <span class="json-number">$1</span>').replace(/(?<=:)\s*(true|false)/g, ' <span class="json-boolean">$1</span>').replace(/(?<=:)\s*(null)/g, ' <span class="json-null">$1</span>').replace(/([{}[\],:])/g, '<span class="json-punctuation">$1</span>');
|
|
6
|
+
} catch (e) {
|
|
7
|
+
return escapeHtml(jsonString);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const calculateLineCount = (text)=>{
|
|
11
|
+
if (!text) return 1;
|
|
12
|
+
const lines = text.split('\n').length;
|
|
13
|
+
return lines;
|
|
14
|
+
};
|
|
15
|
+
export { calculateLineCount, highlightJson };
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -4,4 +4,5 @@ export * from "./components/Page/index.js";
|
|
|
4
4
|
export * from "./components/InfiniteList/index.js";
|
|
5
5
|
export * from "./components/Menu/index.js";
|
|
6
6
|
export * from "./components/DataTable/index.js";
|
|
7
|
+
export * from "./features/JsonEditor/index.js";
|
|
7
8
|
export * from "./http-client/index.js";
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|