listpage-next 0.0.236 → 0.0.237
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/Card/index.d.ts +1 -1
- package/dist/features/ChatClient/ui/ConversationDropdownMenu/index.js +2 -38
- package/dist/features/ChatClient/ui/ConversationDropdownMenu/utils.d.ts +1 -0
- package/dist/features/ChatClient/ui/ConversationDropdownMenu/utils.js +36 -0
- package/dist/features/JsonEditor/CodeEditor.d.ts +6 -0
- package/dist/features/JsonEditor/CodeEditor.js +122 -0
- package/dist/features/JsonEditor/ErrorMessage.d.ts +3 -0
- package/dist/features/JsonEditor/ErrorMessage.js +67 -0
- package/dist/features/JsonEditor/JsonEditor.d.ts +10 -0
- package/dist/features/JsonEditor/JsonEditor.js +127 -0
- package/dist/features/JsonEditor/Toolbar.d.ts +8 -0
- package/dist/features/JsonEditor/Toolbar.js +61 -0
- package/dist/features/JsonEditor/index.d.ts +1 -1
- package/dist/features/JsonEditor/index.js +1 -1
- package/dist/features/JsonEditor/types.d.ts +8 -0
- package/dist/features/JsonEditor/types.js +0 -0
- package/dist/features/JsonEditor/utils.d.ts +6 -2
- package/dist/features/JsonEditor/utils.js +47 -10
- package/package.json +3 -2
- package/dist/features/JsonEditor/Container.d.ts +0 -12
- package/dist/features/JsonEditor/Container.js +0 -122
- package/dist/features/JsonEditor/LineNumberEditor.d.ts +0 -10
- package/dist/features/JsonEditor/LineNumberEditor.js +0 -186
- package/dist/features/JsonEditor/style.d.ts +0 -13
- package/dist/features/JsonEditor/style.js +0 -185
|
@@ -4,7 +4,7 @@ import { PageLoading } from "../../../../components/index.js";
|
|
|
4
4
|
import { useRequest } from "ahooks";
|
|
5
5
|
import { Button, Dropdown, Tooltip } from "antd";
|
|
6
6
|
import styled_components from "styled-components";
|
|
7
|
-
import
|
|
7
|
+
import { getConversationsGroup } from "./utils.js";
|
|
8
8
|
const ConversationDropdownMenu = (props)=>{
|
|
9
9
|
const { request, onSelect, onDelete, activeKey } = props;
|
|
10
10
|
const { data, run: refresh, loading, mutate } = useRequest(()=>request(), {
|
|
@@ -40,43 +40,7 @@ const ConversationDropdownMenu = (props)=>{
|
|
|
40
40
|
if (item.id !== activeKey) onSelect?.(item);
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
|
-
const
|
|
44
|
-
const startOfWeek = now.startOf('day').subtract(now.day(), 'day');
|
|
45
|
-
const getTime = (it)=>it.updatedAt || it.createdAt || it.time || it.date || void 0;
|
|
46
|
-
const list = data?.list ?? [];
|
|
47
|
-
const isToday = (t)=>dayjs(t).isSame(now, 'day');
|
|
48
|
-
const isYesterday = (t)=>dayjs(t).isSame(now.clone().subtract(1, 'day'), 'day');
|
|
49
|
-
const inWeek = (t)=>{
|
|
50
|
-
const d = dayjs(t);
|
|
51
|
-
return d.isAfter(startOfWeek) || d.isSame(startOfWeek, 'day');
|
|
52
|
-
};
|
|
53
|
-
const inMonth = (t)=>dayjs(t).isSame(now, 'month');
|
|
54
|
-
const today = list.filter((it)=>{
|
|
55
|
-
const t = getTime(it);
|
|
56
|
-
if (!t) return false;
|
|
57
|
-
return isToday(t);
|
|
58
|
-
});
|
|
59
|
-
const yesterday = list.filter((it)=>{
|
|
60
|
-
const t = getTime(it);
|
|
61
|
-
if (!t) return false;
|
|
62
|
-
return isYesterday(t);
|
|
63
|
-
});
|
|
64
|
-
const week = list.filter((it)=>{
|
|
65
|
-
const t = getTime(it);
|
|
66
|
-
if (!t) return false;
|
|
67
|
-
return inWeek(t) && !isToday(t) && !isYesterday(t);
|
|
68
|
-
});
|
|
69
|
-
const month = list.filter((it)=>{
|
|
70
|
-
const t = getTime(it);
|
|
71
|
-
if (!t) return false;
|
|
72
|
-
return inMonth(t) && !inWeek(t) && !isToday(t) && !isYesterday(t);
|
|
73
|
-
});
|
|
74
|
-
const groups = {
|
|
75
|
-
今天: today,
|
|
76
|
-
昨天: yesterday,
|
|
77
|
-
本周内: week,
|
|
78
|
-
本月内: month
|
|
79
|
-
};
|
|
43
|
+
const groups = getConversationsGroup(data?.list ?? []);
|
|
80
44
|
const groupEntries = Object.entries(groups).filter(([_, arr])=>arr.length);
|
|
81
45
|
const menus = [];
|
|
82
46
|
groupEntries.forEach(([label, arr], index)=>{
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getConversationsGroup<T>(list: T[]): Record<string, T[]>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
function getConversationsGroup(list) {
|
|
3
|
+
const now = dayjs();
|
|
4
|
+
const startOfWeek = now.startOf('day').subtract(now.day(), 'day');
|
|
5
|
+
const getTime = (it)=>it.updatedAt || it.createdAt || it.time || it.date || void 0;
|
|
6
|
+
const isToday = (t)=>dayjs(t).isSame(now, 'day');
|
|
7
|
+
const isYesterday = (t)=>dayjs(t).isSame(now.clone().subtract(1, 'day'), 'day');
|
|
8
|
+
const inWeek = (t)=>{
|
|
9
|
+
const d = dayjs(t);
|
|
10
|
+
return d.isAfter(startOfWeek) || d.isSame(startOfWeek, 'day');
|
|
11
|
+
};
|
|
12
|
+
const inMonth = (t)=>dayjs(t).isSame(now, 'month');
|
|
13
|
+
const today = [];
|
|
14
|
+
const yesterday = [];
|
|
15
|
+
const week = [];
|
|
16
|
+
const month = [];
|
|
17
|
+
const year = [];
|
|
18
|
+
list.forEach((it)=>{
|
|
19
|
+
const t = getTime(it);
|
|
20
|
+
if (!t) return;
|
|
21
|
+
if (isToday(t)) return void today.push(it);
|
|
22
|
+
if (isYesterday(t)) return void yesterday.push(it);
|
|
23
|
+
if (inWeek(t)) return void week.push(it);
|
|
24
|
+
if (inMonth(t)) return void month.push(it);
|
|
25
|
+
if (dayjs(t).isSame(now, 'year')) return void year.push(it);
|
|
26
|
+
});
|
|
27
|
+
const groups = {
|
|
28
|
+
今天: today,
|
|
29
|
+
昨天: yesterday,
|
|
30
|
+
本周内: week,
|
|
31
|
+
本月内: month,
|
|
32
|
+
今年内: year
|
|
33
|
+
};
|
|
34
|
+
return groups;
|
|
35
|
+
}
|
|
36
|
+
export { getConversationsGroup };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import styled_components from "styled-components";
|
|
4
|
+
import { highlightJson } from "./utils.js";
|
|
5
|
+
const EditorContainer = styled_components.div`
|
|
6
|
+
position: relative;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
10
|
+
'Liberation Mono', 'Courier New', monospace;
|
|
11
|
+
font-size: 0.875rem;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
background: #0d1117;
|
|
14
|
+
`;
|
|
15
|
+
const LineNumbers = styled_components.pre`
|
|
16
|
+
position: absolute;
|
|
17
|
+
top: 0;
|
|
18
|
+
bottom: 0;
|
|
19
|
+
left: 0;
|
|
20
|
+
width: 56px;
|
|
21
|
+
margin: 0;
|
|
22
|
+
padding: 1rem 0.75rem;
|
|
23
|
+
pointer-events: none;
|
|
24
|
+
white-space: pre;
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
color: #6b7280;
|
|
27
|
+
text-align: right;
|
|
28
|
+
user-select: none;
|
|
29
|
+
line-height: 1.625;
|
|
30
|
+
`;
|
|
31
|
+
const HighlightedPre = styled_components.pre`
|
|
32
|
+
position: absolute;
|
|
33
|
+
top: 0;
|
|
34
|
+
right: 0;
|
|
35
|
+
bottom: 0;
|
|
36
|
+
left: 0;
|
|
37
|
+
margin: 0;
|
|
38
|
+
padding: 1rem 1rem 1rem 3.5rem;
|
|
39
|
+
pointer-events: none;
|
|
40
|
+
white-space: pre-wrap;
|
|
41
|
+
word-break: break-word;
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
line-height: 1.625;
|
|
44
|
+
|
|
45
|
+
span.json-token.key {
|
|
46
|
+
color: #7dd3fc;
|
|
47
|
+
}
|
|
48
|
+
span.json-token.string {
|
|
49
|
+
color: #6ee7b7;
|
|
50
|
+
}
|
|
51
|
+
span.json-token.boolean {
|
|
52
|
+
color: #d8b4fe;
|
|
53
|
+
}
|
|
54
|
+
span.json-token.null {
|
|
55
|
+
color: #fb7185;
|
|
56
|
+
}
|
|
57
|
+
span.json-token.number {
|
|
58
|
+
color: #fdba74;
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
const TextAreaOverlay = styled_components.textarea`
|
|
62
|
+
position: absolute;
|
|
63
|
+
top: 0;
|
|
64
|
+
right: 0;
|
|
65
|
+
bottom: 0;
|
|
66
|
+
left: 0;
|
|
67
|
+
width: 100%;
|
|
68
|
+
height: 100%;
|
|
69
|
+
padding: 1rem 1rem 1rem 3.5rem;
|
|
70
|
+
background: transparent;
|
|
71
|
+
color: transparent;
|
|
72
|
+
caret-color: #ffffff;
|
|
73
|
+
outline: none;
|
|
74
|
+
resize: none;
|
|
75
|
+
white-space: pre-wrap;
|
|
76
|
+
overflow: auto;
|
|
77
|
+
z-index: 10;
|
|
78
|
+
transition: color 0.2s ease;
|
|
79
|
+
`;
|
|
80
|
+
const CodeEditor = ({ value, onChange })=>{
|
|
81
|
+
const textareaRef = useRef(null);
|
|
82
|
+
const preRef = useRef(null);
|
|
83
|
+
const lineRef = useRef(null);
|
|
84
|
+
const handleScroll = ()=>{
|
|
85
|
+
if (textareaRef.current) {
|
|
86
|
+
if (preRef.current) {
|
|
87
|
+
preRef.current.scrollTop = textareaRef.current.scrollTop;
|
|
88
|
+
preRef.current.scrollLeft = textareaRef.current.scrollLeft;
|
|
89
|
+
}
|
|
90
|
+
if (lineRef.current) lineRef.current.scrollTop = textareaRef.current.scrollTop;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const lineCount = value ? value.split('\n').length : 1;
|
|
94
|
+
const lineNumbers = Array.from({
|
|
95
|
+
length: lineCount
|
|
96
|
+
}, (_, i)=>`${i + 1}`).join('\n');
|
|
97
|
+
return /*#__PURE__*/ jsxs(EditorContainer, {
|
|
98
|
+
children: [
|
|
99
|
+
/*#__PURE__*/ jsx(LineNumbers, {
|
|
100
|
+
ref: lineRef,
|
|
101
|
+
"aria-hidden": "true",
|
|
102
|
+
children: lineNumbers
|
|
103
|
+
}),
|
|
104
|
+
/*#__PURE__*/ jsx(HighlightedPre, {
|
|
105
|
+
ref: preRef,
|
|
106
|
+
"aria-hidden": "true",
|
|
107
|
+
dangerouslySetInnerHTML: {
|
|
108
|
+
__html: highlightJson(value) + '<br>'
|
|
109
|
+
}
|
|
110
|
+
}),
|
|
111
|
+
/*#__PURE__*/ jsx(TextAreaOverlay, {
|
|
112
|
+
ref: textareaRef,
|
|
113
|
+
value: value,
|
|
114
|
+
onChange: (e)=>onChange(e.target.value),
|
|
115
|
+
onScroll: handleScroll,
|
|
116
|
+
spellCheck: false,
|
|
117
|
+
placeholder: "在这里输入 JSON..."
|
|
118
|
+
})
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
export { CodeEditor };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { WarningOutlined } from "@ant-design/icons";
|
|
3
|
+
import { Tooltip } from "antd";
|
|
4
|
+
import styled_components from "styled-components";
|
|
5
|
+
const ErrorContent = styled_components.div`
|
|
6
|
+
height: 100%;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
padding: 2rem;
|
|
12
|
+
text-align: center;
|
|
13
|
+
color: #ef4444;
|
|
14
|
+
border-radius: 8px;
|
|
15
|
+
`;
|
|
16
|
+
const ErrorIconSvg = styled_components.svg`
|
|
17
|
+
width: 3rem;
|
|
18
|
+
height: 3rem;
|
|
19
|
+
margin-bottom: 1rem;
|
|
20
|
+
`;
|
|
21
|
+
const ErrorTitle = styled_components.h3`
|
|
22
|
+
font-size: 1.125rem;
|
|
23
|
+
font-weight: 700;
|
|
24
|
+
margin-bottom: 0.5rem;
|
|
25
|
+
`;
|
|
26
|
+
const ErrorText = styled_components.p`
|
|
27
|
+
font-size: 0.875rem;
|
|
28
|
+
word-break: break-all;
|
|
29
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
30
|
+
'Liberation Mono', 'Courier New', monospace;
|
|
31
|
+
`;
|
|
32
|
+
const StyledWarningIcon = styled_components(WarningOutlined)`
|
|
33
|
+
color: red;
|
|
34
|
+
font-size: 14px;
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
`;
|
|
37
|
+
const ErrorMessage = (props)=>{
|
|
38
|
+
const { error } = props;
|
|
39
|
+
if (!error) return /*#__PURE__*/ jsx(Fragment, {});
|
|
40
|
+
return /*#__PURE__*/ jsx(Tooltip, {
|
|
41
|
+
color: "white",
|
|
42
|
+
title: /*#__PURE__*/ jsxs(ErrorContent, {
|
|
43
|
+
children: [
|
|
44
|
+
/*#__PURE__*/ jsx(ErrorIconSvg, {
|
|
45
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
46
|
+
fill: "none",
|
|
47
|
+
viewBox: "0 0 24 24",
|
|
48
|
+
stroke: "currentColor",
|
|
49
|
+
children: /*#__PURE__*/ jsx("path", {
|
|
50
|
+
strokeLinecap: "round",
|
|
51
|
+
strokeLinejoin: "round",
|
|
52
|
+
strokeWidth: 2,
|
|
53
|
+
d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
54
|
+
})
|
|
55
|
+
}),
|
|
56
|
+
/*#__PURE__*/ jsx(ErrorTitle, {
|
|
57
|
+
children: "JSON 格式错误"
|
|
58
|
+
}),
|
|
59
|
+
/*#__PURE__*/ jsx(ErrorText, {
|
|
60
|
+
children: error
|
|
61
|
+
})
|
|
62
|
+
]
|
|
63
|
+
}),
|
|
64
|
+
children: /*#__PURE__*/ jsx(StyledWarningIcon, {})
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
export { ErrorMessage };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type JsonValue } from './types';
|
|
2
|
+
export interface JsonEditorProps {
|
|
3
|
+
defaultValue?: JsonValue;
|
|
4
|
+
value?: JsonValue;
|
|
5
|
+
onChange?: (v: JsonValue) => void;
|
|
6
|
+
}
|
|
7
|
+
export interface JsonEditorHandle {
|
|
8
|
+
update: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const JsonEditor: import("react").ForwardRefExoticComponent<JsonEditorProps & import("react").RefAttributes<JsonEditorHandle>>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Flex, message } from "antd";
|
|
3
|
+
import { forwardRef, useImperativeHandle, useState } from "react";
|
|
4
|
+
import { Card } from "../../components/index.js";
|
|
5
|
+
import styled_components from "styled-components";
|
|
6
|
+
import { Toolbar } from "./Toolbar.js";
|
|
7
|
+
import { CodeEditor } from "./CodeEditor.js";
|
|
8
|
+
import { formatJson, minifyJson, validateJson } from "./utils.js";
|
|
9
|
+
import { ErrorMessage } from "./ErrorMessage.js";
|
|
10
|
+
const EditorWrapper = styled_components.div`
|
|
11
|
+
flex: 1;
|
|
12
|
+
display: flex;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
position: relative;
|
|
15
|
+
min-height: 200px;
|
|
16
|
+
height: 100%;
|
|
17
|
+
color: #e5e7eb;
|
|
18
|
+
`;
|
|
19
|
+
const LeftPane = styled_components.div`
|
|
20
|
+
flex: 1;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
border-right: 1px solid #1f2937;
|
|
24
|
+
transition: all 300ms ease;
|
|
25
|
+
width: 100%;
|
|
26
|
+
`;
|
|
27
|
+
const EditorBody = styled_components.div`
|
|
28
|
+
flex: 1;
|
|
29
|
+
position: relative;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
`;
|
|
32
|
+
const InfoBar = styled_components.div`
|
|
33
|
+
position: absolute;
|
|
34
|
+
bottom: 8px;
|
|
35
|
+
right: 16px;
|
|
36
|
+
font-size: 12px;
|
|
37
|
+
color: #6b7280;
|
|
38
|
+
pointer-events: none;
|
|
39
|
+
background: rgba(17, 24, 39, 0.8);
|
|
40
|
+
padding: 4px 8px;
|
|
41
|
+
border-radius: 4px;
|
|
42
|
+
`;
|
|
43
|
+
const JsonEditor = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
44
|
+
const { value, onChange, defaultValue } = props;
|
|
45
|
+
const initialText = void 0 !== value ? JSON.stringify(value, null, 2) : defaultValue ? JSON.stringify(defaultValue, null, 2) : '';
|
|
46
|
+
const [jsonInput, setJsonInput] = useState(initialText);
|
|
47
|
+
const [validation, setValidation] = useState({
|
|
48
|
+
isValid: true,
|
|
49
|
+
data: value
|
|
50
|
+
});
|
|
51
|
+
const updateInput = (next)=>{
|
|
52
|
+
setJsonInput(next);
|
|
53
|
+
const result = validateJson(next);
|
|
54
|
+
setValidation(result);
|
|
55
|
+
if (onChange) if (next.trim()) {
|
|
56
|
+
if (result.isValid) {
|
|
57
|
+
console.log(result);
|
|
58
|
+
onChange(result.data);
|
|
59
|
+
}
|
|
60
|
+
} else onChange(null);
|
|
61
|
+
};
|
|
62
|
+
useImperativeHandle(ref, ()=>({
|
|
63
|
+
update: ()=>{
|
|
64
|
+
updateInput(initialText);
|
|
65
|
+
}
|
|
66
|
+
}), [
|
|
67
|
+
initialText,
|
|
68
|
+
updateInput
|
|
69
|
+
]);
|
|
70
|
+
const handleFormat = ()=>{
|
|
71
|
+
const formatted = formatJson(jsonInput);
|
|
72
|
+
updateInput(formatted);
|
|
73
|
+
};
|
|
74
|
+
const handleMinify = ()=>{
|
|
75
|
+
const minified = minifyJson(jsonInput);
|
|
76
|
+
updateInput(minified);
|
|
77
|
+
};
|
|
78
|
+
const handleCopy = ()=>{
|
|
79
|
+
navigator.clipboard.writeText(jsonInput);
|
|
80
|
+
message.success('复制成功');
|
|
81
|
+
};
|
|
82
|
+
return /*#__PURE__*/ jsx(Card, {
|
|
83
|
+
title: /*#__PURE__*/ jsxs(Flex, {
|
|
84
|
+
align: "center",
|
|
85
|
+
gap: 6,
|
|
86
|
+
children: [
|
|
87
|
+
/*#__PURE__*/ jsx("span", {
|
|
88
|
+
children: "JSON"
|
|
89
|
+
}),
|
|
90
|
+
/*#__PURE__*/ jsx(ErrorMessage, {
|
|
91
|
+
error: validation.error
|
|
92
|
+
})
|
|
93
|
+
]
|
|
94
|
+
}),
|
|
95
|
+
extra: /*#__PURE__*/ jsx(Flex, {
|
|
96
|
+
align: "center",
|
|
97
|
+
gap: 8,
|
|
98
|
+
children: /*#__PURE__*/ jsx(Toolbar, {
|
|
99
|
+
disabled: !validation.isValid,
|
|
100
|
+
onFormat: handleFormat,
|
|
101
|
+
onMinify: handleMinify,
|
|
102
|
+
onCopy: handleCopy
|
|
103
|
+
})
|
|
104
|
+
}),
|
|
105
|
+
children: /*#__PURE__*/ jsx(EditorWrapper, {
|
|
106
|
+
children: /*#__PURE__*/ jsx(LeftPane, {
|
|
107
|
+
children: /*#__PURE__*/ jsxs(EditorBody, {
|
|
108
|
+
children: [
|
|
109
|
+
/*#__PURE__*/ jsx(CodeEditor, {
|
|
110
|
+
value: jsonInput,
|
|
111
|
+
onChange: updateInput
|
|
112
|
+
}),
|
|
113
|
+
/*#__PURE__*/ jsxs(InfoBar, {
|
|
114
|
+
children: [
|
|
115
|
+
"长度: ",
|
|
116
|
+
jsonInput.length,
|
|
117
|
+
" | 行数: ",
|
|
118
|
+
jsonInput.split('\n').length
|
|
119
|
+
]
|
|
120
|
+
})
|
|
121
|
+
]
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
export { JsonEditor };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface ToolbarProps {
|
|
2
|
+
disabled?: boolean;
|
|
3
|
+
onFormat: () => void;
|
|
4
|
+
onMinify: () => void;
|
|
5
|
+
onCopy: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const Toolbar: ({ onFormat, onMinify, onCopy, disabled, }: ToolbarProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Tooltip } from "antd";
|
|
3
|
+
import { Braces, Copy, FileArchive } from "lucide-react";
|
|
4
|
+
import styled_components from "styled-components";
|
|
5
|
+
const ToolbarContainer = styled_components.div`
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
`;
|
|
9
|
+
const ActionButton = styled_components(Button)`
|
|
10
|
+
&:hover {
|
|
11
|
+
color: #ffffff;
|
|
12
|
+
background-color: rgba(31, 41, 55, 0.5);
|
|
13
|
+
}
|
|
14
|
+
`;
|
|
15
|
+
const Toolbar = ({ onFormat, onMinify, onCopy, disabled })=>/*#__PURE__*/ jsxs(ToolbarContainer, {
|
|
16
|
+
children: [
|
|
17
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
18
|
+
title: "格式化",
|
|
19
|
+
children: /*#__PURE__*/ jsx(ActionButton, {
|
|
20
|
+
disabled: disabled,
|
|
21
|
+
size: "small",
|
|
22
|
+
type: "text",
|
|
23
|
+
onClick: onFormat,
|
|
24
|
+
icon: /*#__PURE__*/ jsx(Braces, {
|
|
25
|
+
style: {
|
|
26
|
+
fontSize: 16
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
}),
|
|
31
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
32
|
+
title: "压缩",
|
|
33
|
+
children: /*#__PURE__*/ jsx(ActionButton, {
|
|
34
|
+
disabled: disabled,
|
|
35
|
+
size: "small",
|
|
36
|
+
type: "text",
|
|
37
|
+
onClick: onMinify,
|
|
38
|
+
icon: /*#__PURE__*/ jsx(FileArchive, {
|
|
39
|
+
style: {
|
|
40
|
+
fontSize: 16
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
}),
|
|
45
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
46
|
+
title: "复制",
|
|
47
|
+
children: /*#__PURE__*/ jsx(ActionButton, {
|
|
48
|
+
disabled: disabled,
|
|
49
|
+
size: "small",
|
|
50
|
+
type: "text",
|
|
51
|
+
onClick: onCopy,
|
|
52
|
+
icon: /*#__PURE__*/ jsx(Copy, {
|
|
53
|
+
style: {
|
|
54
|
+
fontSize: 16
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
]
|
|
60
|
+
});
|
|
61
|
+
export { Toolbar };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { JsonEditor, type JsonEditorProps } from './
|
|
1
|
+
export { JsonEditor, type JsonEditorProps } from './JsonEditor';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { JsonEditor } from "./
|
|
1
|
+
import { JsonEditor } from "./JsonEditor.js";
|
|
2
2
|
export { JsonEditor };
|
|
File without changes
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const
|
|
1
|
+
import type { ValidationResult, JsonValue } from './types';
|
|
2
|
+
export declare const validateJson: (jsonString: string) => ValidationResult;
|
|
3
|
+
export declare const formatJson: (jsonString: string) => string;
|
|
4
|
+
export declare const minifyJson: (jsonString: string) => string;
|
|
5
|
+
export declare const getType: (value: JsonValue) => string;
|
|
6
|
+
export declare const highlightJson: (json: string) => string;
|
|
@@ -1,15 +1,52 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const validateJson = (jsonString)=>{
|
|
2
|
+
if (!jsonString.trim()) return {
|
|
3
|
+
isValid: true,
|
|
4
|
+
data: null
|
|
5
|
+
};
|
|
4
6
|
try {
|
|
5
|
-
|
|
7
|
+
const data = JSON.parse(jsonString);
|
|
8
|
+
return {
|
|
9
|
+
isValid: true,
|
|
10
|
+
data
|
|
11
|
+
};
|
|
6
12
|
} catch (e) {
|
|
7
|
-
|
|
13
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
14
|
+
return {
|
|
15
|
+
isValid: false,
|
|
16
|
+
error: message
|
|
17
|
+
};
|
|
8
18
|
}
|
|
9
19
|
};
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
20
|
+
const formatJson = (jsonString)=>{
|
|
21
|
+
try {
|
|
22
|
+
const obj = JSON.parse(jsonString);
|
|
23
|
+
return JSON.stringify(obj, null, 2);
|
|
24
|
+
} catch (_) {
|
|
25
|
+
return jsonString;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const minifyJson = (jsonString)=>{
|
|
29
|
+
try {
|
|
30
|
+
const obj = JSON.parse(jsonString);
|
|
31
|
+
return JSON.stringify(obj);
|
|
32
|
+
} catch (_) {
|
|
33
|
+
return jsonString;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const getType = (value)=>{
|
|
37
|
+
if (null === value) return 'null';
|
|
38
|
+
if (Array.isArray(value)) return 'array';
|
|
39
|
+
return typeof value;
|
|
40
|
+
};
|
|
41
|
+
const highlightJson = (json)=>{
|
|
42
|
+
if (!json) return '';
|
|
43
|
+
const htmlEscaped = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
44
|
+
return htmlEscaped.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, (match)=>{
|
|
45
|
+
let cls = 'json-token number';
|
|
46
|
+
if (/^"/.test(match)) cls = /:$/.test(match) ? 'json-token key' : 'json-token string';
|
|
47
|
+
else if (/true|false/.test(match)) cls = 'json-token boolean';
|
|
48
|
+
else if (/null/.test(match)) cls = 'json-token null';
|
|
49
|
+
return `<span class="${cls}">${match}</span>`;
|
|
50
|
+
});
|
|
14
51
|
};
|
|
15
|
-
export {
|
|
52
|
+
export { formatJson, getType, highlightJson, minifyJson, validateJson };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "listpage-next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.237",
|
|
4
4
|
"description": "A React component library for creating filter forms with Ant Design",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"@tiptap/extension-hard-break": "~3.10.7",
|
|
70
70
|
"@tiptap/core": "~3.10.7",
|
|
71
71
|
"@tiptap/pm": "~3.10.7",
|
|
72
|
-
"prosemirror-state": "~1.4.4"
|
|
72
|
+
"prosemirror-state": "~1.4.4",
|
|
73
|
+
"lucide-react": "~0.555.0"
|
|
73
74
|
}
|
|
74
75
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
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;
|
|
@@ -1,122 +0,0 @@
|
|
|
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 };
|
|
@@ -1,10 +0,0 @@
|
|
|
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 {};
|
|
@@ -1,186 +0,0 @@
|
|
|
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:
|
|
9
|
-
'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
|
10
|
-
font-size: 12px;
|
|
11
|
-
line-height: 1.5;
|
|
12
|
-
overflow: hidden;
|
|
13
|
-
box-sizing: border-box;
|
|
14
|
-
`;
|
|
15
|
-
const LineNumbers = styled_components.div`
|
|
16
|
-
padding: 4px 8px;
|
|
17
|
-
text-align: right;
|
|
18
|
-
background-color: #f0f0f0;
|
|
19
|
-
color: #999;
|
|
20
|
-
overflow: hidden;
|
|
21
|
-
user-select: none;
|
|
22
|
-
flex-shrink: 0;
|
|
23
|
-
border-right: 1px solid #ddd;
|
|
24
|
-
font-family: inherit;
|
|
25
|
-
font-size: inherit;
|
|
26
|
-
line-height: inherit;
|
|
27
|
-
box-sizing: border-box;
|
|
28
|
-
`;
|
|
29
|
-
const TextAreaContainer = styled_components.div`
|
|
30
|
-
flex: 1;
|
|
31
|
-
position: relative;
|
|
32
|
-
overflow: hidden;
|
|
33
|
-
box-sizing: border-box;
|
|
34
|
-
`;
|
|
35
|
-
const StyledTextArea = styled_components.textarea`
|
|
36
|
-
position: absolute;
|
|
37
|
-
top: 0;
|
|
38
|
-
left: 0;
|
|
39
|
-
width: 100%;
|
|
40
|
-
height: 100%;
|
|
41
|
-
padding: 4px 8px;
|
|
42
|
-
border: none;
|
|
43
|
-
resize: none;
|
|
44
|
-
font-family: inherit;
|
|
45
|
-
font-size: inherit;
|
|
46
|
-
line-height: inherit;
|
|
47
|
-
background-color: transparent;
|
|
48
|
-
outline: none;
|
|
49
|
-
overflow: auto;
|
|
50
|
-
white-space: pre;
|
|
51
|
-
tab-size: 2;
|
|
52
|
-
box-sizing: border-box;
|
|
53
|
-
color: transparent; /* 文字透明 */
|
|
54
|
-
caret-color: #000; /* 但光标是黑色的 */
|
|
55
|
-
|
|
56
|
-
${(props)=>props.hasError && `
|
|
57
|
-
box-shadow: inset 0 0 0 1px #ff4d4f;
|
|
58
|
-
`}
|
|
59
|
-
|
|
60
|
-
&:focus {
|
|
61
|
-
box-shadow: none;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
&::-webkit-scrollbar {
|
|
65
|
-
width: 8px;
|
|
66
|
-
height: 8px;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
&::-webkit-scrollbar-track {
|
|
70
|
-
background: #f1f1f1;
|
|
71
|
-
border-radius: 4px;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
&::-webkit-scrollbar-thumb {
|
|
75
|
-
background: #c1c1c1;
|
|
76
|
-
border-radius: 4px;
|
|
77
|
-
|
|
78
|
-
&:hover {
|
|
79
|
-
background: #a8a8a8;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
`;
|
|
83
|
-
const HighlightPreview = styled_components.div`
|
|
84
|
-
position: absolute;
|
|
85
|
-
top: 0;
|
|
86
|
-
left: 0;
|
|
87
|
-
width: 100%;
|
|
88
|
-
height: 100%;
|
|
89
|
-
padding: 4px 8px;
|
|
90
|
-
border: none;
|
|
91
|
-
resize: none;
|
|
92
|
-
font-family: inherit;
|
|
93
|
-
font-size: inherit;
|
|
94
|
-
line-height: inherit;
|
|
95
|
-
background-color: #fafafa;
|
|
96
|
-
pointer-events: none;
|
|
97
|
-
overflow: auto;
|
|
98
|
-
white-space: pre;
|
|
99
|
-
tab-size: 2;
|
|
100
|
-
box-sizing: border-box;
|
|
101
|
-
|
|
102
|
-
.json-key {
|
|
103
|
-
color: #92278f; /* 紫色 */
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.json-string {
|
|
107
|
-
color: #3a9aed; /* 蓝色 */
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.json-number {
|
|
111
|
-
color: #25aae1; /* 青色 */
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.json-boolean {
|
|
115
|
-
color: #f98280; /* 红色 */
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.json-null {
|
|
119
|
-
color: #f18f01; /* 橙色 */
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.json-punctuation {
|
|
123
|
-
color: #333; /* 深灰色 */
|
|
124
|
-
}
|
|
125
|
-
`;
|
|
126
|
-
const LineNumberEditor = ({ value, onChange, readOnly = false, hasError = false, placeholder = '' })=>{
|
|
127
|
-
const lineNumbersRef = useRef(null);
|
|
128
|
-
const textAreaRef = useRef(null);
|
|
129
|
-
const previewRef = useRef(null);
|
|
130
|
-
useEffect(()=>{
|
|
131
|
-
if (lineNumbersRef.current) {
|
|
132
|
-
const lineNumbers = [];
|
|
133
|
-
const lineCount = calculateLineCount(value);
|
|
134
|
-
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>`);
|
|
135
|
-
lineNumbersRef.current.innerHTML = lineNumbers.join('');
|
|
136
|
-
}
|
|
137
|
-
}, [
|
|
138
|
-
value
|
|
139
|
-
]);
|
|
140
|
-
useEffect(()=>{
|
|
141
|
-
if (previewRef.current) previewRef.current.innerHTML = highlightJson(value);
|
|
142
|
-
}, [
|
|
143
|
-
value
|
|
144
|
-
]);
|
|
145
|
-
const handleScroll = ()=>{
|
|
146
|
-
if (textAreaRef.current && lineNumbersRef.current && previewRef.current) {
|
|
147
|
-
const scrollTop = textAreaRef.current.scrollTop;
|
|
148
|
-
const scrollLeft = textAreaRef.current.scrollLeft;
|
|
149
|
-
lineNumbersRef.current.scrollTop = scrollTop;
|
|
150
|
-
previewRef.current.scrollTop = scrollTop;
|
|
151
|
-
previewRef.current.scrollLeft = scrollLeft;
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
const syncCursorPosition = ()=>{
|
|
155
|
-
if (textAreaRef.current && previewRef.current) {
|
|
156
|
-
previewRef.current.scrollTop = textAreaRef.current.scrollTop;
|
|
157
|
-
previewRef.current.scrollLeft = textAreaRef.current.scrollLeft;
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
return /*#__PURE__*/ jsxs(EditorContainer, {
|
|
161
|
-
children: [
|
|
162
|
-
/*#__PURE__*/ jsx(LineNumbers, {
|
|
163
|
-
ref: lineNumbersRef
|
|
164
|
-
}),
|
|
165
|
-
/*#__PURE__*/ jsxs(TextAreaContainer, {
|
|
166
|
-
children: [
|
|
167
|
-
/*#__PURE__*/ jsx(HighlightPreview, {
|
|
168
|
-
ref: previewRef
|
|
169
|
-
}),
|
|
170
|
-
/*#__PURE__*/ jsx(StyledTextArea, {
|
|
171
|
-
ref: textAreaRef,
|
|
172
|
-
value: value,
|
|
173
|
-
onChange: (e)=>onChange(e.target.value),
|
|
174
|
-
readOnly: readOnly,
|
|
175
|
-
hasError: hasError,
|
|
176
|
-
placeholder: placeholder,
|
|
177
|
-
onScroll: handleScroll,
|
|
178
|
-
onMouseUp: syncCursorPosition,
|
|
179
|
-
onKeyUp: syncCursorPosition
|
|
180
|
-
})
|
|
181
|
-
]
|
|
182
|
-
})
|
|
183
|
-
]
|
|
184
|
-
});
|
|
185
|
-
};
|
|
186
|
-
export { LineNumberEditor };
|
|
@@ -1,13 +0,0 @@
|
|
|
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;
|
|
@@ -1,185 +0,0 @@
|
|
|
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:
|
|
73
|
-
'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
|
74
|
-
font-size: 12px;
|
|
75
|
-
line-height: 1.5;
|
|
76
|
-
overflow: hidden;
|
|
77
|
-
box-sizing: border-box;
|
|
78
|
-
`;
|
|
79
|
-
const LineNumbers = styled.div`
|
|
80
|
-
padding: 4px 8px;
|
|
81
|
-
text-align: right;
|
|
82
|
-
background-color: #f0f0f0;
|
|
83
|
-
color: #999;
|
|
84
|
-
overflow: hidden;
|
|
85
|
-
user-select: none;
|
|
86
|
-
flex-shrink: 0;
|
|
87
|
-
border-right: 1px solid #ddd;
|
|
88
|
-
font-family: inherit;
|
|
89
|
-
font-size: inherit;
|
|
90
|
-
line-height: inherit;
|
|
91
|
-
box-sizing: border-box;
|
|
92
|
-
`;
|
|
93
|
-
const TextAreaContainer = styled.div`
|
|
94
|
-
flex: 1;
|
|
95
|
-
position: relative;
|
|
96
|
-
overflow: hidden;
|
|
97
|
-
box-sizing: border-box;
|
|
98
|
-
`;
|
|
99
|
-
const StyledTextArea = styled.textarea`
|
|
100
|
-
position: absolute;
|
|
101
|
-
top: 0;
|
|
102
|
-
left: 0;
|
|
103
|
-
width: 100%;
|
|
104
|
-
height: 100%;
|
|
105
|
-
padding: 4px 8px;
|
|
106
|
-
border: none;
|
|
107
|
-
resize: none;
|
|
108
|
-
font-family: inherit;
|
|
109
|
-
font-size: inherit;
|
|
110
|
-
line-height: inherit;
|
|
111
|
-
background-color: #fafafa;
|
|
112
|
-
outline: none;
|
|
113
|
-
overflow: auto;
|
|
114
|
-
white-space: pre;
|
|
115
|
-
tab-size: 2;
|
|
116
|
-
box-sizing: border-box;
|
|
117
|
-
|
|
118
|
-
${(props)=>props.hasError && `
|
|
119
|
-
box-shadow: inset 0 0 0 1px #ff4d4f;
|
|
120
|
-
`}
|
|
121
|
-
|
|
122
|
-
&:focus {
|
|
123
|
-
box-shadow: none;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
&::-webkit-scrollbar {
|
|
127
|
-
width: 8px;
|
|
128
|
-
height: 8px;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
&::-webkit-scrollbar-track {
|
|
132
|
-
background: #f1f1f1;
|
|
133
|
-
border-radius: 4px;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
&::-webkit-scrollbar-thumb {
|
|
137
|
-
background: #c1c1c1;
|
|
138
|
-
border-radius: 4px;
|
|
139
|
-
|
|
140
|
-
&:hover {
|
|
141
|
-
background: #a8a8a8;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
`;
|
|
145
|
-
const HighlightPreview = styled.div`
|
|
146
|
-
position: absolute;
|
|
147
|
-
top: 0;
|
|
148
|
-
left: 0;
|
|
149
|
-
width: 100%;
|
|
150
|
-
height: 100%;
|
|
151
|
-
padding: 4px 8px;
|
|
152
|
-
border: none;
|
|
153
|
-
resize: none;
|
|
154
|
-
font-family: inherit;
|
|
155
|
-
font-size: inherit;
|
|
156
|
-
line-height: inherit;
|
|
157
|
-
background-color: transparent;
|
|
158
|
-
pointer-events: none;
|
|
159
|
-
overflow: auto;
|
|
160
|
-
white-space: pre;
|
|
161
|
-
tab-size: 2;
|
|
162
|
-
color: transparent;
|
|
163
|
-
box-sizing: border-box;
|
|
164
|
-
|
|
165
|
-
.json-key {
|
|
166
|
-
color: #92278f;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.json-string {
|
|
170
|
-
color: #3a9aed;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.json-number {
|
|
174
|
-
color: #25aae1;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
.json-boolean {
|
|
178
|
-
color: #f98280;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.json-punctuation {
|
|
182
|
-
color: #333;
|
|
183
|
-
}
|
|
184
|
-
`;
|
|
185
|
-
export { CardHeader, EditorContainer, EditorWrapper, ErrorMessage, HeaderActions, HeaderTitle, HighlightPreview, JsonEditorContainer, LineNumbers, StyledTextArea, TextAreaContainer };
|